In SQL server 2008 R2. Is it possible to do a rollback on a single update command?
I know there are other questiones like this on SO but i havent seen one specific for 2008 R2 and hence I may get the same answer, if that is the case then we can close this thread.
I did the a simple update without any transactions commands:
UPDATE myTable SET col1=somevalue WHERE....
Of course you can use explicit transactions such as
BEGIN TRAN
UPDATE ...
ROLLBACK
but I don't think you are asking about that?
If you have the option SET IMPLICIT_TRANSACTIONS ON then the command will not be committed or rolled back until you do so explicitly but this is not the default behaviour.
By default transactions are auto committed so when the command finishes successfully the results of the update will be committed. If the update was to encounter an error - including the connection being killed mid update it would auto rollback.
If your database is in full recovery mode you might want to try reading transaction log, finding which rows were affected and then reverting the update.
However, this is not supported by default, because MS stored transaction log in its own format that is not well documented.
Solution is to use commands such as DBCC LOG or fn_log or third party tool such as ApexSQL Log which does all of this automatically but comes with a price.
If you need more details, here are couple of posts on reading transaction log:
Read the log file (*.LDF) in sql server 2008
SQL Server Transaction Log Explorer/Analyzer
Related
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 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.
I want to wrap my SQL deployment script in a transaction (containing a bunch of schema changes). I am doing this because if one part of it fails, I want the db to revert to what it was before I ran the script.
I have a few simple questions I would like to have resolved prior to pushing these changes:
Is it necessary to explicitly call COMMIT on the transaction at the bottom of the script?
Is it necessary to explicitly check for errors and call ROLLBACK at the bottom, or will simply using a transaction provide this effect?
Yes.
Yes.
You should also investigate SET XACT_ABORT ON. SET XACT_ABORT ON instructs SQL Server to rollback the entire transaction and abort the batch when a run-time error occurs.
This article Error Handling in SQL 2005 and Later is worth reading.
My application (C++ using SQL Native Client with SQL Server 2000) is consistently finding its way into a hanging state. I believe this is because a transaction is left uncommitted someplace on a table and a SELECT query on that table, as a result of the open transaction, is blocking.
Unfortunately, I'm really having trouble determining where the hanging transaction might be in my code. Is there any way to get SQL Server to indicate what queries have been run on an uncommitted transaction?
if you have admin (sa) proviliges, you can run sp_Who, or sp_Who2
to show all server activity, by Spid, Run
Exec sp_Who2 [SpidNumber]
to just see the one session you are interested in...
To directly see open transactions, run
DBCC OPENTRAN (T-SQL)
Displays information about the oldest active transaction and the oldest distributed and nondistributed replicated transactions, if any, within the specified database. Results are displayed only if there is an active transaction or if the database contains replication information. An informational message is displayed if there are no active transactions.
Syntax
DBCC OPENTRAN
( {'database_name' | database_id}
) [ WITH TABLERESULTS [, NO_INFOMSGS]
]
Sql Server should, however, automatically rollback any open transaction when a user session is terminated.