{"id":195,"date":"2016-04-15T09:39:27","date_gmt":"2016-04-15T08:39:27","guid":{"rendered":"https:\/\/sqldoubleg.live-website.com\/?p=195"},"modified":"2016-04-15T14:57:08","modified_gmt":"2016-04-15T13:57:08","slug":"back-to-basics-lock-escalation-in-sql-server","status":"publish","type":"post","link":"https:\/\/www.sqldoubleg.com\/es\/2016\/04\/15\/back-to-basics-lock-escalation-in-sql-server\/","title":{"rendered":"Back To Basics, Lock Escalation in SQL Server"},"content":{"rendered":"<p>Sometimes something innocuous can take our application down, that&#8217;s why it&#8217;s important to get back to the basics&nbsp;Today at work we&#8217;ve had a very common request, no big deal, just a couple of UPDATE which affect tens of thousands of rows in a couple of tables independently.<\/p>\n<p>I can say I&#8217;ve been there, done that before so I passed this to my unfortunate junior, so I can learn enough from his walkthrough to write this post.<\/p>\n<p>To accomplish this sort of task, we can take a simple approach, you write the SELECT statement and once you&#8217;re happy with the results, convert it to UPDATE to get the job done. Easy peasy. <\/p>\n<p>Sure, and I&#8217;d do it that way if I were allowed to have downtime. Errr? Did I say downtime? Yes, indeed.<\/p>\n<p>Most of you have realized already what I&#8217;m talking about, but if not, just read the title again \ud83d\ude42<\/p>\n<p>You&#8217;re right, LOCK ESCALATION. <\/p>\n<p>&nbsp;<br \/>\n<strong>The theory<\/strong><\/p>\n<p>According to <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/ms184286(v=sql.105).aspx\" target=\"_blank\">Books Online<\/a><\/p>\n<blockquote><p>Lock escalation is the process of converting many fine-grain locks into fewer coarse-grain locks, reducing system overhead while increasing the probability of concurrency contention<\/p><\/blockquote>\n<p>And for non partitioned tables also states that <\/p>\n<blockquote><p>Lock escalation is triggered when lock escalation is not disabled on the table and a single Transact-SQL statement acquires at least 5,000 locks<\/p><\/blockquote>\n<p>That in English means that if you try to update too many rows at once, you will lock the whole table until your updates finish. <\/p>\n<p>Obviously in that process, no one will be allowed access that table. If you have users working while you&#8217;re planning to UPDATE thousands of rows, that is something to always keep in mind.<\/p>\n<p>In a simple scenario, we can say that the threshold would be close to that number, although, that number can vary depending on other factors like available memory on the server. However for this example I&#8217;ll be alone in the server, so the threshold shouldn&#8217;t be much different than that stated in BOL.<\/p>\n<p>First let me show you this phenomenon. <\/p>\n<p>&nbsp;<br \/>\n<strong>How it happens<\/strong><\/p>\n<p>Open a new tab in SSMS and run<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE AdventureWorks2014 \r\n\r\nBEGIN TRAN\r\n\r\nUPDATE TOP(100) Person.Address\r\nSET AddressLine1 = AddressLine1\r\n<\/pre>\n<p>We can observe how SQL Server will stop anyone from accessing those rows, open another tab, and run <\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE AdventureWorks2014\r\n\r\nSELECT * FROM sys.dm_tran_locks\r\n<\/pre>\n<p>So we can see how SQL Server locks each row individually<\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/01_hundred_locks.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/01_hundred_locks.png\" alt=\"01_hundred_locks\" width=\"1244\" height=\"516\" class=\"aligncenter size-full wp-image-196\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/01_hundred_locks.png 1244w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/01_hundred_locks-300x124.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/01_hundred_locks-1024x425.png 1024w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/01_hundred_locks-150x62.png 150w\" sizes=\"(max-width: 1244px) 100vw, 1244px\" \/><\/a><\/p>\n<p>Also if we try to access those rows, we will have to wait, otherwise we are free to access other rows not affected by the transaction. If we run <\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE AdventureWorks2014\r\n\r\nSELECT TOP 100 * FROM Person.Address\r\n<\/pre>\n<p>We will have to wait until the current transaction ends by a COMMIT or a ROLLBACK.<\/p>\n<p>But if we pick some other rows, there is no problem at all and rows are returned.<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE AdventureWorks2014\r\n\r\nSELECT TOP 100 * FROM Person.Address\r\nORDER BY AddressID DESC\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/02_SELECT_TOP_100_DESC.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/02_SELECT_TOP_100_DESC.png\" alt=\"02_SELECT_TOP_100_DESC\" width=\"1243\" height=\"536\" class=\"aligncenter size-full wp-image-197\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/02_SELECT_TOP_100_DESC.png 1243w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/02_SELECT_TOP_100_DESC-300x129.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/02_SELECT_TOP_100_DESC-1024x442.png 1024w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/02_SELECT_TOP_100_DESC-150x65.png 150w\" sizes=\"(max-width: 1243px) 100vw, 1243px\" \/><\/a><\/p>\n<p>Now it&#8217;s when we push it a bit further to see how LOCK ESCALATION happens; I&#8217;d love to have a magic number that always works, but as I said, it varies<\/p>\n<p>I&#8217;ll play it safe by going a bit bigger than 5000 Updates, so you will see how rows are not locked anymore but the table is.<\/p>\n<p>First let&#8217;s ROLLBACK our transaction and open a new one<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE AdventureWorks2014 \r\n\r\nROLLBACK \r\n\r\nBEGIN TRAN\r\n\r\nUPDATE TOP(5500) Person.Address\r\nSET AddressLine1 = AddressLine1\r\n<\/pre>\n<p>Now if we switch to our other tab and run again<\/p>\n<pre class=\"brush: tsql; title: ; notranslate\" title=\"\">\r\nUSE AdventureWorks2014\r\n\r\nSELECT * FROM sys.dm_tran_locks\r\n<\/pre>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/03_Table_LOCKED.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/03_Table_LOCKED.png\" alt=\"03_Table_LOCKED\" width=\"1245\" height=\"230\" class=\"aligncenter size-full wp-image-198\" srcset=\"https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/03_Table_LOCKED.png 1245w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/03_Table_LOCKED-300x55.png 300w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/03_Table_LOCKED-1024x189.png 1024w, https:\/\/www.sqldoubleg.com\/wp-content\/uploads\/2016\/04\/03_Table_LOCKED-150x28.png 150w\" sizes=\"(max-width: 1245px) 100vw, 1245px\" \/><\/a><\/p>\n<p>See there is an eXclusive lock on the object, not on each individual row anymore, which means no other user can access the entire object while the transaction is running, and that my friends, means downtime.<\/p>\n<p>Any attempt to access the table will have to wait until the open transaction finish. You can see the output of <a href=\"http:\/\/sqlblog.com\/blogs\/adam_machanic\/archive\/tags\/sp_5F00_whoisactive\/default.aspx\" target=\"_blank\">sp_WhoIsActive<\/a> if I try to do a SELECT<\/p>\n<p><a href=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/04_sp_WhoIsActive.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/sqldoubleg.live-website.com\/wp-content\/uploads\/2016\/04\/04_sp_WhoIsActive.png\" alt=\"04_sp_WhoIsActive\" width=\"1241\" height=\"186\" class=\"aligncenter size-full wp-image-199\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\n<strong>Conclusion<\/strong><\/p>\n<p>So, now you&#8217;ve seen how something which seems completely harmless can indeed make your users (and boss) very upset. <\/p>\n<p>LOCK ESCALATION is a feature to keep in mind when you work with big data sets. There is much more than what I&#8217;ve told you here, so please refer to <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/ms184286(v=sql.105).aspx\" target=\"_blank\">BOL<\/a> to get a deeper understanding.<\/p>\n<p>I look forward to seeing how you guys usually approach this kind of scenarios, so please feel free to comment and thanks for reading<br \/>\n&nbsp;<br \/>\n&nbsp;<br \/>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes something innocuous can take our application down, that&#8217;s why it&#8217;s important to get back to the basics&nbsp;Today at work we&#8217;ve had a very common request, no big deal, just a couple&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[33,5,12],"_links":{"self":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/195"}],"collection":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/comments?post=195"}],"version-history":[{"count":1,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/195\/revisions"}],"predecessor-version":[{"id":269,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/195\/revisions\/269"}],"wp:attachment":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/media?parent=195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/categories?post=195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/tags?post=195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}