<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://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>Search results matching tags 'Internals' and 'Transactions'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Internals,Transactions&amp;orTags=0</link><description>Search results matching tags 'Internals' and 'Transactions'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>TSQL Tuesday #11:Rolling Back TRUNCATE TABLE</title><link>http://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><description>&lt;A href="http://sankarreddy.com/2010/10/invitation-to-participate-in-t-sql-tuesday-11-misconceptions-in-sql-server/" target=_blank&gt;&lt;IMG style="BORDER-RIGHT-WIDTH:0px;MARGIN:5px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title=TSQL2sDay150x150 border=0 alt=TSQL2sDay150x150 align=right src="http://sankarreddy.com/wp-content/uploads/2010/10/TSQL2sDay150x150.jpg" width=150 height=150&gt;&lt;/A&gt; 
&lt;P&gt;“It ain't what people don't know that hurts them it's what they know that ain't so”&amp;nbsp; &lt;BR&gt;-- commonly attributed to Mark Twain&lt;/P&gt;
&lt;P&gt;SQL Server has been around for a long time now, and people who learn one version well sometimes have&amp;nbsp; monumental task when a new version comes out. They need to figure out what changed. The "What's New" documentation usually gives a good idea of the major new features, but sometimes when a more minor feature just change a bit, it's may get overlooked in all the hoopla of learning about the BIG new stuff.&lt;/P&gt;
&lt;P&gt;One change that occurred very long ago that many people still haven't hooked into is that fact that a TRUNCATE TABLE operation can be rolled back! Even in my advanced classes, with some of the best DBAs out there, when I start talking about TRUNCATE TABLE, there are frequently one or two people who think it is unlogged and thus can't be rolled back. &lt;/P&gt;
&lt;P&gt;Let me state now… THIS IS NOT TRUE.&lt;/P&gt;
&lt;P&gt;And in fact, it is very easy to prove that it is not true… but if you don't suspect that it is not true, why would you even test it?&lt;/P&gt;
&lt;P&gt;TRUNCATE TABLE is logged, but SQL Server doesn't log every single row as it TRUNCATEs the table, so you might think that this command falls into the category of commands we call 'minimally logged'. But although indeed minimal information is logged for this operation, it is not technically in that category. The official 'minimally logged' operations also cause a bit to be set in a big bit map, so that when you are running in BULK_LOGGED recovery model and make a log backup, SQL Server can capture all the data involved in 'minimally logged' operations into the transaction log. This allows the data to be recovered when restoring from backup. &lt;/P&gt;
&lt;P&gt;But for TRUNCATE TABLE, SQL Server only logs the fact that the operation happened, along with information about the pages and extents that were deallocated. So that's minimal information. And by recording which pages and extents were deallocated, there's enough information to roll back, by just REallocating those pages. A log&amp;nbsp; backup only needs the information that the TRUNCATE TABLE occurred. And to restore the TRUNCATE TABLE, the operation is just reapplied. The data involved is not needed during RESTORE (like it would be for a true 'minimally logged' operation like a BULK INSERT). &lt;/P&gt;
&lt;P&gt;So what if the transaction in which the TRUNCATE TABLE occurs stay open for a long time? How does SQL Server know not to reuse the pages that belonged to the table? It turns out the pages and/or extents involved are locked with an eXclusive lock, and just like all X locks, they are held until the end of the transaction.&amp;nbsp; And as long as the pages or extents are locked, they can't be deallocated, and certainly cannot be reused. &lt;/P&gt;
&lt;P&gt;So here's some code to see for yourself. I'll make a copy of a table from the AdventureWorks database:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;USE AdventureWorks &lt;BR&gt;GO &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;IF EXISTS (SELECT * FROM sys.tables &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE name = 'Products' &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AND schema_id = 1) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DROP TABLE dbo.Products; &lt;BR&gt;GO &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;SELECT * INTO dbo.Products &lt;BR&gt;FROM Production.Product; &lt;BR&gt;GO&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now we'll look at the count of rows, and the pages that belong to the table.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;SELECT COUNT(*) FROM dbo.Products; &lt;BR&gt;GO &lt;BR&gt;DBCC IND('AdventureWorks', 'Products', -1); &lt;BR&gt;GO&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;We get a count of 504 rows and the following pages:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;File&amp;nbsp;&amp;nbsp;&amp;nbsp; Page &lt;BR&gt;-----&amp;nbsp;&amp;nbsp; ------- &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 23027 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 23029 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 23030 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 26992 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 26993 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33352 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33353 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33354 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33355 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33356 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33357 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 42486 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 42487 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 42488 &lt;BR&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 42489&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Next, start a transaction and truncate the table. Verify that DBCC IND shows no pages belonging to the table and the count is 0. Then, look at the locks.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;BEGIN TRAN &lt;BR&gt;TRUNCATE TABLE dbo.Products; &lt;BR&gt;SELECT COUNT(*) FROM dbo.Products; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;DBCC IND('AdventureWorks', 'Products', -1); &lt;BR&gt;DBCC EXTENTINFO('AdventureWorks', 'Products', -1); &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;SELECT resource_type, resource_description, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; request_mode FROM sys.dm_tran_locks &lt;BR&gt;WHERE&amp;nbsp; resource_type IN ('EXTENT', 'PAGE') &lt;BR&gt;AND&amp;nbsp;&amp;nbsp; resource_database_id = DB_ID('AdventureWorks');&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You should see no rows from DBCC IND, and 0 rows from count(*). But the locks info should return something like:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;resource_type resource_description request_mode &lt;BR&gt;------------- -------------------- ------------ &lt;BR&gt;EXTENT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:33352&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:42486&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;EXTENT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:42488&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:42487&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:42488&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:42489&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:23027&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:23030&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:23029&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:26992&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X &lt;BR&gt;PAGE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1:26993&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; X&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So the extent and page locks include all the pages that we saw in the DBCC IND output. (Remember, an extent is 8 contiguous pages, starting at the one that describes the extent.)&lt;/P&gt;
&lt;P&gt;Only after you ROLLBACK the transaction will the locks be released, and you should see all the rows and pages back in the table again.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2&gt;ROLLBACK TRAN; &lt;BR&gt;GO &lt;BR&gt;SELECT COUNT(*) FROM dbo.Products; &lt;BR&gt;DBCC IND('AdventureWorks', 'Products', -1); &lt;BR&gt;GO&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So now you know!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff size=4&gt;~Kalen&lt;/FONT&gt;&lt;/P&gt;</description></item><item><title>Geek City: How SQL Server Detects the Correct Versioned Rows</title><link>http://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><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;</description></item></channel></rss>