Sometimes when (for example) setting a database offline by executing the following command, an exception will be thrown, because one or more clients is connected:
ALTER DATABASE <dbname> SET OFFLINE
According to this answer one solution is to use with rollback immediate at the end:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
But why is actually this disconnecting other clients? It sounds like a very non-obvious way to force disconnections, although it works.
You can't take the database offline while other Users have transactions running on it so you're going to have to disconnect the users one way or another to take the database offline.
If you were being polite you could ask all your users to finish doing whatever they were doing before you took the database offline
but if that's not practical including the option
WITH ROLLBACK IMMEDIATE
Means that all current transactions are Rolled back (the database is reset to the point where the transaction started) . You could also use
WITH ROLLBACK AFTER 60 SECONDS
but I've never had to
If you could take a database offline while there were unfinished transactions were running then the database would be in an unstable state with the change neither made nor cancelled
From MSDN
WITH <termination>::=
Specifies when to roll back incomplete transactions when the database
is transitioned from one state to another. If the termination clause
is omitted, the ALTER DATABASE statement waits indefinitely if there
is any lock on the database. Only one termination clause can be
specified, and it follows the SET clauses.
Where termination would be ROLLBACK IMMEDIATE in your case.
Related
We have a situation where procedures with DML operations are often run by different users at different point in time, and I need to shutdown my database for recovery purpose.
So, I want to know what happens to the PL/SQL blocks (procedures with DML operations in this case) if shutdown immediate or shutdown transactional command is issued
In case of normal SQL command shutdown immediate will just rollback the DML operations and Shutdown transactional will wait for the transaction to complete, but what with PL/SQL blocks.
I have searched by not found answer to this question, every where reference to SQL command is only given.
You can find all you need, here.
Extract from page:
Shutting Down with the NORMAL Clause
To shut down a database in normal situations, use the SHUTDOWN command
with the NORMAL clause:
SHUTDOWN NORMAL
The NORMAL clause is optional, because this is the
default shutdown method if no clause is provided.
Normal database shutdown proceeds with the following conditions:
No new connections are allowed after the statement is issued.
Before the database is shut down, the database waits for all currently
connected users to disconnect from the database.
The next startup of the database will not require any instance
recovery procedures.
Shutting Down with the IMMEDIATE Clause
Use immediate database shutdown only in the following situations:
To initiate an automated and unattended backup
When a power shutdown is going to occur soon
When the database or one of its applications is functioning
irregularly and you cannot contact users to ask them to log off or
they are unable to log off
To shut down a database immediately, use the SHUTDOWN command with the
IMMEDIATE clause:
SHUTDOWN IMMEDIATE
My web application is connected to a SQL Server 2016 Express database, and we have been plagued by data locks in certain areas of the system.
My colleague noticed just today that, when a KILL process was used to kill a long-running transaction, that several transactions that had ostensibly already been committed were rolled-back.
I have checked using #vladV's script on In SQL Server, how do I know what transaction mode I'm currently using? that in fact the database seems to be in auto-commit mode.
So therefore it must be that that something in the database is opening a new transaction and not committing it.
So I found in the database four stored procedures which contain the following
SET IMPLICIT_TRANSACTIONS ON
... code ...
IF ##TRAN_COUNT>0 COMMIT WORK
Am I right in saying that in some/most situations such a stored procedure would leave transactions open, even after exiting the stored procedure, and that this could be the source of the data-lock problems?
And if so, then could I just remedy the code by doing
SET IMPLICIT_TRANSACTIONS OFF
when the stored procedure exits?
Am I right in saying that in some/most situations such a stored procedure would leave transactions open
Some. Depends on what comes after. With IMPLICIT TRANSACTIONS in SQL Server, transactions are not automatically started until you run a query that reads the database.
could I just remedy the code by doing SET IMPLICIT_TRANSACTIONS OFF
No. That won't end any open transactions.
Note that COMMIT doesn't reduce the ##trancount to 0. It decrements it by 1. So if you have multiple BEGIN TRAN statements, or an explicit BEGIN TRAN after an transaction has implicitly begun, then you will need multiple COMMITs.
You might try
WHILE ##trancount > 0 COMMIT TRANSACTION
which will definitely commit any outstanding transactions.
Everytime when I update the table rows in SQL Server, the update runs successfully and I also confirm and it shows that the rows were updated. However, the following day when I check I find that the updates I made have rolled back. I also checked if there are any transactions opened but there is none. I do not run my update statement in a transaction, therefore I do not have to commit any transaction after.
This is been happening for a while and it is really irritating.
Any help will be highly appreciated.
It could be possible that your server or data access mechanism you're using (ie. ADO.NET) isn't configured to auto-commit transactions. This MSDN site states;
Autocommit mode is the default transaction management mode of the SQL
Server Database Engine. Every Transact-SQL statement is committed or
rolled back when it completes. If a statement completes successfully,
it is committed; if it encounters any error, it is rolled back. A
connection to an instance of the Database Engine operates in
autocommit mode whenever this default mode has not been overridden by
either explicit or implicit transactions. Autocommit mode is also the
default mode for ADO, OLE DB, ODBC, and DB-Library.
Try explicitly putting your UPDATE into a transaction and committing to see if that saves. Also ask your DBA to see if there is any setting on SQL Server that has change the default transaction management mode to set autocommit to false.
I wonder a case. I have a project using a database (Oracle and Mssql). My project has a framework that I manage transactions.
In thread I open a database connection and start a transaction.(In transaction, there are many update and insert queries.) While code is running, somehow connection is closed. Because I have try-catch block, I catch exception and rollback transaction. BUT; if my connection is closed because some reasons, how rollback query can run on database? How can I handle this situation? If I open a new connection and rollback, does it work?
Thanks.
There is a term you should know - ACID compliancy:
Atomicity is an all-or-none proposition;
Consistency guarantees that a transaction never leaves your database in a half-finished state.
Isolation keeps transactions separated from each other until they’re finished.
Durability guarantees that the database will keep track of pending changes in such a way that the server can recover from an abnormal termination.
Concerning MySQL
In order to get this at MySQL, you have to use Transaction Safe Tables (TST). Advantages of Transaction-Safe Tables:
Safer. Even if MySQL crashes or you get hardware problems, you can get your data back, either by automatic recovery or from a backup + the transaction log.
You can combine many statements and accept these all in one go with the COMMIT command.
You can execute ROLLBACK to ignore your changes (if you are not running in auto-commit mode).
If an update fails, all your changes will be restored.
Concerning SQL Server
You should read "Transaction Behavior On Lost Connection" MSDN forum topic.
To understand better what lays behind MS SQL Server transactions, read a good article "Locks and Duration of Transactions in MS SQL Server"
Make sure you are not using any autocommit feature (I think that's enabled by default in some MySQL installations). If you do all your commits "manually", a broken connection will just result in you never committing the transaction and so it won't ever get written.
You cannot reconnect to rollback in most database systems.
I have recently tried a big merge of 2 databases. We recreated the schema from Database 2 into Database 1 and created a script to transfer all data from database 2 into Database 1. This script takes about 35 min to run and have transaction handling with:
BEGIN TRANSACTION
...
IF(##error<>0)
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
The full script is a bit sensitive but here is some SQL that have the same structure: http://pastebin.com/GWJ3ZnkF
We ran the script and all data was transfered without errors. We tested the systems running with the new combined database (removed access rights to the old database).
But as a last task we wanted to take the old database offline to make sure no one used that database. To do this we used:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
This was bad. After this line of SQL code all data in the combined database that we just copied was suddenly gone. I first asumed it wasn't really finished so the "Rollback immediate" sounds like it have performed a rollback on my transaction..
But why? Wasn't the transaction allready committed?
Also I tried running the same script again a few times but after every attempt no data was copied even if it said the script was successfull. I have no idea why... did it remember my offline rollback somehow?
What is really happening to my connections?
Sounds like you had a pending transaction uncommitted and you forced it to rollback, loosing some of the work. The rest is explained by how your scripts are structured. Is unlikely your script had a single transaction from start to bottom. Only the last transaction was rolled back, so the database was left now in a state in which it is 'half copied'. Probably your script does various checks and this intermediate state sends the script on the 'ELSE' branches where it does not do the proper work (ie. apparently does nothing).
W/o posting the exact script, is all speculation anyway.
Right now you need to restore the database to a consistent state, the one before your data copy. Use the backup you took before the data move (you did take a backup, right?). for extra credit, make sure your script is idempotent and works correctly on a half-updated database.
I'd double-check to make sure that there are no outstanding transactions. Either go through the file and count the number of BEGIN TRANSACTION vs COMMIT TRANSACTION lines, or add a statement to the end of it to SELECT ##TRANCOUNT to ensure that there are no open transactions remaining.
If your data has been committed, there should be no way it can be lost by disconnecting you.
WITH ROLLBACK IMMEDIATE:
All incomplete transactions will be rolled back and any other
connections to the database will be
immediately disconnected.
Sounds like someone got the 2 databases mixed up or maybe there is an outstanding transaction?.... Can you post your entire script?
Ref: ALTER DATABASE.
Rather than only checking ##ERROR, inspect ##TRANCOUNT as well.