<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www2.sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kalen Delaney : Transactions</title><link>http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Transactions/default.aspx</link><description>Tags: Transactions</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>TSQL Tuesday #11:Rolling Back TRUNCATE TABLE</title><link>http://www2.sqlblog.com/blogs/kalen_delaney/archive/2010/10/12/tsql-tuesday-11-rolling-back-truncate-table.aspx</link><pubDate>Tue, 12 Oct 2010 20:02:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:29343</guid><dc:creator>Kalen Delaney</dc:creator><slash:comments>8</slash:comments><comments>http://www2.sqlblog.com/blogs/kalen_delaney/comments/29343.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/kalen_delaney/commentrss.aspx?PostID=29343</wfw:commentRss><description>“It ain't what people don't know that hurts them it's what they know that ain't so” -- commonly attributed to Mark Twain SQL Server has been around for a long time now, and people who learn one version well sometimes have monumental task when a new version...(&lt;a href="http://www2.sqlblog.com/blogs/kalen_delaney/archive/2010/10/12/tsql-tuesday-11-rolling-back-truncate-table.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=29343" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/internals/default.aspx">internals</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/locking/default.aspx">locking</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/T-SQL+Tuesday/default.aspx">T-SQL Tuesday</category></item><item><title>Geek City: How Many Rows?</title><link>http://www2.sqlblog.com/blogs/kalen_delaney/archive/2009/12/07/how-many-rows.aspx</link><pubDate>Mon, 07 Dec 2009 17:59:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:19568</guid><dc:creator>Kalen Delaney</dc:creator><slash:comments>6</slash:comments><comments>http://www2.sqlblog.com/blogs/kalen_delaney/comments/19568.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/kalen_delaney/commentrss.aspx?PostID=19568</wfw:commentRss><description>In my last post, I told you I'd post something technical before I left for Sweden. I almost made it. I wrote this in the Seattle airport, but wasn't able to post it until I got to Stockholm. For as long as I've been working with SQL Server, I've been...(&lt;a href="http://www2.sqlblog.com/blogs/kalen_delaney/archive/2009/12/07/how-many-rows.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=19568" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/metadata/default.aspx">metadata</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/rowcount/default.aspx">rowcount</category></item><item><title>Geek City: Why I still need Sysprocesses</title><link>http://www2.sqlblog.com/blogs/kalen_delaney/archive/2008/06/29/why-i-still-need-sysprocesses.aspx</link><pubDate>Mon, 30 Jun 2008 03:48:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:7566</guid><dc:creator>Kalen Delaney</dc:creator><slash:comments>19</slash:comments><comments>http://www2.sqlblog.com/blogs/kalen_delaney/comments/7566.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/kalen_delaney/commentrss.aspx?PostID=7566</wfw:commentRss><description>&lt;P&gt;I've said many times that my favorite new feature in SQL Server 2005 is the new metadata, in particular the new Dynamic Management Objects. When I have to do troubleshooting on a SQL Server 2000 system, it is worse than painful, not to have my favorite tools like &lt;EM&gt;sys.dm_tran_locks&lt;/EM&gt;, &lt;EM&gt;sys.dm_exec_cached_plans&lt;/EM&gt; and&lt;BR&gt;&lt;EM&gt;sys.dm_exec_query_plan&lt;/EM&gt;. By now, on the eve of the release of the version AFTER SQL Server 2005, my transition to the new metadata is almost complete. &lt;/P&gt;
&lt;P&gt;With one notable exception...&lt;/P&gt;
&lt;P&gt;I have always used &lt;EM&gt;sysprocesses&lt;/EM&gt; constantly for troubleshooting information. Although most of the useful information that allows me to see what sessions are using lots of memory, or performing lots of I/O, can found in &lt;EM&gt;sys.dm_exec_sessions&lt;/EM&gt;, there is one piece of information that isn't there. &lt;EM&gt;Sysprocesses&lt;/EM&gt; contains a columns called &lt;EM&gt;open_tran&lt;/EM&gt; which reflects the transaction&amp;nbsp; nesting of each session. If a session issues four BEGIN TRAN commands, with no COMMITs or ROLLBACKs, their session will have an &lt;EM&gt;open_tran&lt;/EM&gt; value in &lt;EM&gt;sysprocesses&lt;/EM&gt; of 4. Any &lt;EM&gt;open_tran&lt;/EM&gt; value greater than 0 might mean that a transaction is holding locks and blocking other processes, or it might be keeping the transaction log from being cleared. If you ever notice &lt;EM&gt;open_tran&lt;/EM&gt; values in higher than 2 or 3, it's a pretty good indication that a developer doesn't know much about SQL Server transaction management. I use this value all the time, and once had to troubleshoot a system where dozens of connections had open_tran values in the 20s and 30s! (For more details about nesting transactions, see my &lt;A href="http://sqlblog.com/blogs/kalen_delaney/archive/2007/08/13/did-you-know-nesting-transactions.aspx" target=_blank&gt;earlier post&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;So imagine my surprise when I discovered that the &lt;EM&gt;sys.dm_exec_sessions&lt;/EM&gt; view, which is supposed to 'replace' &lt;EM&gt;sysprocesses&lt;/EM&gt; in SQL Server 2005, has no column to provide this information!&amp;nbsp; Another view, &lt;EM&gt;sys.dm_exec_requests&lt;/EM&gt;, has a column called &lt;EM&gt;open_transaction_count&lt;/EM&gt;, which you might think would be the same thing. And it actually is the same information, but the &lt;EM&gt;sys.dm_exec_requests&lt;/EM&gt; view only returns rows for sessions that are currently active, i.e. currently running a query. The need for examining the &lt;EM&gt;open_tran&lt;/EM&gt; value is greatest when looking at those sessions that aren't doing anything, but are just sitting there with an open transaction. Those are the processes that you need to troubleshoot. I had felt that the omission of &lt;EM&gt;open_tran&lt;/EM&gt; (or &lt;EM&gt;open_transaction_count&lt;/EM&gt;) from &lt;EM&gt;sys.dm_exec_sessions&lt;/EM&gt; was just an oversight, and it would be 'fixed' in the next release. But it appears I am to be disappointed. I just checked &lt;EM&gt;sys.dm_exec_sessions&lt;/EM&gt; in RC0, and there is still no &lt;EM&gt;open_transaction_count&lt;/EM&gt; column.&lt;/P&gt;
&lt;P&gt;So long live &lt;EM&gt;sysprocesses&lt;/EM&gt;!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff size=4&gt;~Kalen&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=7566" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/metadata/default.aspx">metadata</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/DMVs/default.aspx">DMVs</category></item><item><title>Geek City: How SQL Server Detects the Correct Versioned Rows</title><link>http://www2.sqlblog.com/blogs/kalen_delaney/archive/2008/04/03/how-sql-server-detects-the-correct-versioned-rows.aspx</link><pubDate>Thu, 03 Apr 2008 19:16:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:6033</guid><dc:creator>Kalen Delaney</dc:creator><slash:comments>4</slash:comments><comments>http://www2.sqlblog.com/blogs/kalen_delaney/comments/6033.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/kalen_delaney/commentrss.aspx?PostID=6033</wfw:commentRss><description>&lt;P&gt;Here is a question I just received from the feedback page on my web site: 
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;I have finished the book &amp;lt;the storage engine&amp;gt; and like it very much. I am now reading &amp;lt;query tuning and optimization&amp;gt; &lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;I know in the READ COMMITTED SNAPSHOT isolation, when a row is being modified in a transaction, it generates an old committed version so another transaction can read it without being blocked. &lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;But I don’t know how SQL Server uses SNAPSHOT isolation to prevent Phantom Read being happening. &lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;In SERIALIZABLE isolation the ranged key or the whole table is locked, but in SNAPSHOT isolation, it can NOT generate any committed version since the row does NOT exist at the moment. So how does it know that the newly inserted data should not be included in the second SELECT statement?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;-Tom&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Tom is correct in that INSERTS do not generate versioned rows. However, SQL Server is able to keep track of when each change was made under snapshot isolation. Once a database is enabled for snapshots, every rows inserted, deleted or modified gets an additional 14 bytes of overhead added to it. These bytes contain 2 pieces of information. First is a row pointer to the previous committed version of the row, which is stored in the version store in tempdb. This pointer is only used for deleted and updated rows, since there will be no previous values for newly inserted rows. &lt;/P&gt;
&lt;P&gt;However, these extra bytes also include a value called XSN, or transaction sequence number, which you can think of like a timestamp for a database. Any database enabled for snapshot keeps an internal XSN value, that is incremented each time any change is made, or any snapshot select is performed. The metadata also keeps track of all active transactions, and what the XSN was when the transaction started. It uses the view &lt;EM&gt;sys.dm_tran_active_snapshot_database_transactions&lt;/EM&gt; for this.&amp;nbsp; So when you are reading data, SQL Server will look at the XSN number in each row, and not return any rows that have an XSN value greater than the XSN value at the time the transaction started.&lt;/P&gt;
&lt;P&gt;I hope this helps!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff size=5&gt;~Kalen&lt;/FONT&gt; 
&lt;P&gt;&lt;A href="http://www.insidesqlserver.com/"&gt;www.InsideSQLServer.com&lt;/A&gt;&lt;BR&gt;&lt;A href="http://www.sqlserverdvd.com/"&gt;www.SQLServerDVD.com&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=6033" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/internals/default.aspx">internals</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Inside+SQL+Server/default.aspx">Inside SQL Server</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/snapshot+isolation/default.aspx">snapshot isolation</category></item><item><title>Did you Know? Nesting Transactions</title><link>http://www2.sqlblog.com/blogs/kalen_delaney/archive/2007/08/13/did-you-know-nesting-transactions.aspx</link><pubDate>Mon, 13 Aug 2007 22:20:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:2199</guid><dc:creator>Kalen Delaney</dc:creator><slash:comments>10</slash:comments><comments>http://www2.sqlblog.com/blogs/kalen_delaney/comments/2199.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/kalen_delaney/commentrss.aspx?PostID=2199</wfw:commentRss><description>&lt;BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Transact-SQL provides three different methods of transaction control: autocommit transactions, explicit transactions and implicit transactions.&lt;/P&gt;
&lt;P&gt;An autocommit transaction is any individual&amp;nbsp;INSERT, UPDATE or DELETE operation, no matter&amp;nbsp;how many rows are affected.&amp;nbsp;As soon as the statement is completed, it is committed, which means that all the corresponding log records, include a COMMIT TRAN log record, are written to the transaction log on disk (your .ldf file).&lt;/P&gt;
&lt;P&gt;If you want to be able to combine multiple statements into a single transaction, or if you want to be able to conditionally rollback the transaction, you can use explicit transaction control, with the BEGIN TRANSACTION (or BEGIN TRAN) and&amp;nbsp;COMMIT TRANSACTION (or COMMIT TRAN) control statements.&amp;nbsp;For example, to make sure both&amp;nbsp;T1&amp;nbsp;and T2 are updated, or&amp;nbsp;neither one is updated, you can use the following pseudo-code:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;BEGIN TRAN&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UPDATE T1 ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UPDATE T2 ...&lt;BR&gt;COMMIT TRAN &amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If there is a system failure after T1 is updated, the transaction will not be committed. It will only be committed if both updates can succeed. &lt;/P&gt;
&lt;P&gt;Also, by using explicit transactions, you can decide to rollback a transaction, after checking for an error condition or for the number of rows affected:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;BEGIN TRAN&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UPDATE T1 ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IF @@error &amp;gt; 0 ROLLBACK TRAN&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE COMMIT TRAN &amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The third type of transaction control, implicit transactions,&amp;nbsp;is not considered a default behavior and is part of the product only to support compatibility with other database products. I'll say a couple of things about it shortly.&lt;/P&gt;
&lt;P&gt;Here is a little quiz I frequently give my students. Suppose I have the following batch:&lt;/P&gt;
&lt;P&gt;BEGIN TRAN&lt;BR&gt;UPDATE T1&lt;BR&gt;BEGIN TRAN&lt;BR&gt;UPDATE T2&lt;BR&gt;BEGIN TRAN&lt;BR&gt;UPDATE T3&lt;BR&gt;COMMIT TRAN&lt;/P&gt;
&lt;P&gt;The quiz question is: What gets committed?&lt;/P&gt;
&lt;P&gt;I usually get a variety of answers including: All the updates, none of the updates, the update to T1, the update to T3. (Nobody suggests the update to T2.)&lt;/P&gt;
&lt;P&gt;It turns out the answer is: None of the above. &lt;/P&gt;
&lt;P&gt;SQL Server keeps an internal counter of how many times BEGIN TRAN has been executed, and you need to execute the same number of COMMIT TRANs to get the real commit to take place. Each BEGIN TRAN increments this internal counter, and each COMMIT TRAN decrements it. Only when the counter gets to 0, will the log records be written out to disk and the transaction will be truly committed. You can look at the value of this counter with the function @@trancount. You can use this function to also see that when you do a ROLLBACK, the counter is immediately set all the way back to 0.&lt;/P&gt;
&lt;P&gt;BEGIN TRAN&lt;BR&gt;SELECT @@trancount&lt;BR&gt;BEGIN TRAN&lt;BR&gt;SELECT @@trancount&lt;BR&gt;BEGIN TRAN&lt;BR&gt;SELECT @@trancount&lt;/P&gt;
&lt;P&gt;ROLLBACK TRAN&lt;BR&gt;SELECT @@trancount&lt;/P&gt;
&lt;P&gt;So why would you want to have nested transactions, if it really doesn't give you any advantage?&amp;nbsp; The answer to that will have to wait for a future post. This post is about the relationship of nesting transactions to the third type of transaction control: implicit transactions. &lt;/P&gt;
&lt;P&gt;The name 'implicit transactions' is a bit of a misnomer. It is only the BEGIN TRAN that is implicit; the COMMIT TRAN must always be explicit. This means that no transaction will be committed until a COMMIT TRAN is issued. Transactions will begin any time an INSERT, UPDATE, DELETE or SELECT is executed (as well as a few other statements, such as CREATE and DROP, that you can read about in the Books Online) as long as there is not already an open transaction. &lt;/P&gt;
&lt;P&gt;As mentioned, implicit transaction mode is not SQL Server's default. You have to request implicit transaction mode either with a SET statement:&lt;/P&gt;
&lt;P&gt;SET IMPLICIT_TRANSACTIONS ON;&lt;/P&gt;
&lt;P&gt;or by setting the &lt;EM&gt;user_options&lt;/EM&gt; configuration option to have the 2-bit set to 1. You can read about sp_configure 'user options' in the Books Online. Although I don't recommend using implicit transactions, if you're going to use them, I recommend having all sessions use them, but setting the configuration option. To have some sessions using implicit transactions and requiring a COMMIT for every individual INSERT, UPDATE and DELETE and to have other sessions not requiring that closure, seems to be asking for trouble. &lt;/P&gt;
&lt;P&gt;So what happens if you use a BEGIN TRAN when you are in implicit transaction mode? I used to think that the BEGIN TRAN would just be ignored, but it turns out I was wrong.&amp;nbsp;Think about what would happen if you had a normal, implicit mode transaction like this:&lt;/P&gt;
&lt;P&gt;UPDATE&amp;nbsp;T1&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET ... &lt;BR&gt;COMMIT TRAN&lt;/P&gt;
&lt;P&gt;and then suppose someone executes this batch from within an explicit transaction, and put the BEGIN/COMMIT around it:&lt;/P&gt;
&lt;P&gt;BEGIN TRAN&lt;BR&gt;UPDATE&amp;nbsp;T1&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET ... &lt;BR&gt;COMMIT TRAN&lt;BR&gt;COMMIT TRAN&lt;/P&gt;
&lt;P&gt;If the BEGIN TRAN was ignored, the first COMMIT would would set @@trancount to 0 and the second would give an error. You can see this behavior by just executing COMMIT TRAN all by itself. SQL Server generates this message:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Msg 3902, Level 16, State 1, Line 1&lt;BR&gt;The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So if you are in implicit transaction mode, issuing a BEGIN TRAN (which you really shouldn't do) sets @@trancount to 2. This really surprised me when I first noticed it, but then I realized the point of it. When you perform any DML operation, since you are already in a transaction, @@trancount will not be incremented. When you issue the COMMIT for your DML, @@trancount will be decremented to 1. When you issue the COMMIT TRAN to match the BEGIN TRAN, @@trancount will decrement to 0 and the transaction will really be committed.&amp;nbsp; Here's a full script to illustrate the behavior of @@trancount with implicit transactions:&lt;/P&gt;
&lt;P&gt;SET IMPLICIT_TRANSACTIONS OFF;&lt;BR&gt;GO&lt;BR&gt;IF EXISTS (SELECT * FROM sys.objects&lt;BR&gt;WHERE name = 'T1' AND type = 'U')&lt;BR&gt;DROP TABLE T1;&lt;BR&gt;GO&lt;BR&gt;CREATE TABLE T1 (col1 int);&lt;BR&gt;GO&lt;BR&gt;INSERT INTO T1 SELECT 1;&lt;BR&gt;GO &lt;/P&gt;
&lt;P&gt;SET IMPLICIT_TRANSACTIONS ON;&lt;BR&gt;GO&lt;BR&gt;BEGIN TRAN;&lt;BR&gt;SELECT @@trancount;&lt;BR&gt;UPDATE T1&lt;BR&gt;SET col1 = col1 + 1;&lt;BR&gt;COMMIT TRAN;&lt;BR&gt;SELECT @@trancount;&lt;BR&gt;COMMIT TRAN;&lt;BR&gt;SELECT @@trancount;&lt;BR&gt;GO&lt;BR&gt;SET IMPLICIT_TRANSACTIONS OFF;&lt;BR&gt;GO 
&lt;P&gt;Have fun!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff&gt;&lt;STRONG&gt;~Kalen&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=2199" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/implicit+transactions/default.aspx">implicit transactions</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/_40004000_trancount/default.aspx">@@trancount</category><category domain="http://www2.sqlblog.com/blogs/kalen_delaney/archive/tags/Transactions/default.aspx">Transactions</category></item></channel></rss>