{"id":771,"date":"2009-11-13T13:24:00","date_gmt":"2009-11-13T13:24:00","guid":{"rendered":"\/blogs\/paul\/post\/Lock-logging-and-fast-recovery.aspx"},"modified":"2017-08-11T10:24:01","modified_gmt":"2017-08-11T17:24:01","slug":"lock-logging-and-fast-recovery","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/","title":{"rendered":"Lock logging and fast recovery"},"content":{"rendered":"<p style=\"text-align: justify;\">One of the things I love teaching is how the transaction log and logging\/recovery work. I presented a session on this at both PASS and SQL Connections in the last two weeks, and in both sessions I promised to write some blog posts about the deep internals of logging operations. This is the first one in the series. Previous blog posts that dive into logging operations are:<\/p>\n<ul style=\"text-align: justify;\">\n<li><em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/how-do-checkpoints-work-and-what-gets-logged\/\">How do checkpoints work and what gets logged<\/a><\/em> (this also explains how crash recovery starts, using the boot page and the most recent checkpoint log record)<\/li>\n<li><em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/finding-out-who-dropped-a-table-using-the-transaction-log\/\">Finding out who dropped a table using the transaction log<\/a><\/em><\/li>\n<li><em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/how-expensive-are-page-splits-in-terms-of-transaction-log\/\">How expensive are page splits in terms of transaction log?<\/a><\/em><\/li>\n<li><em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/inside-the-storage-engine-more-on-the-circular-nature-of-the-log\/\">Inside the Storage Engine: More on the circular nature of the log<\/a><\/em><\/li>\n<li><em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/ghost-cleanup-redux\/\">Ghost cleanup redux<\/a><\/em><\/li>\n<li><em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/inside-the-storage-engine-ghost-cleanup-in-depth\/\">Inside the Storage Engine: Ghost cleanup in depth<\/a><\/em><\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Ok, on with the show.<\/p>\n<p style=\"text-align: justify;\">SQL Server 2005 introduced a feature called <em>fast recovery<\/em> in Enterprise Edition. This allows a database to become available for use after the first part of recovery (REDO) completes and before the (usually longer running) second part of recovery (UNDO) completes. See my TechNet Magazine article <em><a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/2009.02.logging.aspx\">Understanding Logging and Recovery in SQL Server<\/a><\/em> if you don&#8217;t know what I&#8217;m talking about. But how does SQL Server do this?<\/p>\n<p style=\"text-align: justify;\">The answer is lock logging. A log record describes a single change made to a database. For log records describing changes that can be used as part of UNDO (yes, some changes to the database are one-way only &#8211; for instance PFS page changes), from 2005 onwards the log record also includes a description of which locks were being held at the time the change was made. These locks were necessary to protect the change being made when the original transaction was running (before the crash) and so the same locks will be necessary to protect the anti-operation which reverses the change. I&#8217;ll explain more about these anti-operations in one of the next in-depth logging blog posts.<\/p>\n<p style=\"text-align: justify;\">The Storage Engine does three passes through the log as part of crash recovery. The first pass works out which transactions were committed, and issues readahead of the necessary data file pages into the buffer pool. The second\u00a0pass does REDO and also reads the log records that will be processed as part of the third\u00a0pass (UNDO), looking at the lock description and actually acquiring those locks. For fast recovery, at that point the database is brought online. This is possible because the recovery system knows that it already has the correct locks to guarantee that it can safely generate and perform the anti-operations necessary to perfom UNDO. One side-effect of this is that although the database is available for use, a query may bump into one of the locks being held to allow fast recovery &#8211; in which case it will have to wait for that lock to be dropped as UNDO progresses.<\/p>\n<p style=\"text-align: justify;\">Cool eh?<\/p>\n<p style=\"text-align: justify;\">That was the introduction to allow me to do some gratuitous spelunking around the internals :-) I&#8217;m going to create a few simple examples to show you lock logging in the log. Now, don&#8217;t get confused &#8211; it&#8217;s not logging actual locks (the memory used to hold the lock itself), it&#8217;s just logging a description of which locks were held and in which modes.<\/p>\n<p style=\"text-align: justify;\">Here&#8217;s the script to create a database with a simple table. I&#8217;m using a LOB column and specifically setting it to be stored off row (see <em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/importance-of-choosing-the-right-lob-storage-technique\/\">Importance of choosing the right LOB storage technique<\/a><\/em>) so we can see some text page locks too. I&#8217;m using the <em>SIMPLE<\/em>\u00a0recovery model for simplicity (ha ha) &#8211; so I can clear the log when a checkpoint occurs rather than having to muck around with log backups. I&#8217;ll insert the first row and then clear the log.<\/p>\n<pre class=\"brush: sql; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nCREATE DATABASE LockLogging;\r\nGO\r\nUSE LockLogging;\r\nGO\r\n\r\nCREATE TABLE LockLogTest (c1 INT, c2 INT, c3 VARCHAR (MAX));\r\nGO\r\nEXEC sp_tableoption 'LockLogtest', 'large value types out of row', 'on';\r\nGO\r\n\r\nINSERT INTO LockLogTest VALUES (1, 1, 'a');\r\nGO\r\n\r\nALTER DATABASE LockLogging SET RECOVERY SIMPLE;\r\nGO\r\nCHECKPOINT;\r\nGO\r\n<\/pre>\n<p style=\"text-align: justify;\">Now let&#8217;s try the first operation &#8211; a simple insert &#8211; and look at the log records using <em>fn_dblog<\/em> (and I&#8217;m skipping the checkpoint log records):<\/p>\n<pre class=\"brush: sql; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nINSERT INTO LockLogTest VALUES (2, 2, 'b');\r\nGO\r\nSELECT &#x5B;Operation], &#x5B;Context], &#x5B;Page ID], &#x5B;Slot ID], &#x5B;Number of Locks] AS Locks, &#x5B;Lock Information]\r\nFROM fn_dblog (NULL, NULL);\r\nGO\r\n<\/pre>\n<pre class=\"brush: plain; gutter: false; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nOperation        Context       Page ID        Slot ID  Locks Lock Information\r\n---------------- ------------- -------------- -------- ----- -------------------------------------------------------------------------------------------------------\r\nLOP_BEGIN_XACT   LCX_NULL      NULL           NULL     NULL  NULL\r\nLOP_INSERT_ROWS  LCX_TEXT_MIX  0001:00000098  1        2     ACQUIRE_LOCK_IX PAGE: 18:1:152; ACQUIRE_LOCK_X RID: 18:1:152:1\r\nLOP_INSERT_ROWS  LCX_HEAP      0001:0000009a  1        3     ACQUIRE_LOCK_IX OBJECT: 18:2073058421:0;ACQUIRE_LOCK_IX PAGE: 18:1:154; ACQUIRE_LOCK_X RID: 18:1:154:1\r\nLOP_COMMIT_XACT  LCX_NULL      NULL           NULL     NULL  NULL\r\n<\/pre>\n<p style=\"text-align: justify;\">We can see page IX and row X locks for the LOB value being inserted into the text page, plus table IX, page IX, and row X locks for the data record being inserted into the heap. The lock resources break out as follows:<\/p>\n<ul style=\"text-align: justify;\">\n<li>18:1:152 is page 152 in file 1 of database ID 18<\/li>\n<li>18:1:152:1 is slot 1 on page 152 in file 1 of database ID 18<\/li>\n<li>18:2073058421:0 is object ID 2073058421 (the object ID of the table LockLogTest) in database ID 18<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Notice also the <em>LOP_BEGIN_XACT<\/em> and <em>LOP_COMMIT_XACT<\/em> log records &#8211;\u00a0even though I didn&#8217;t do an explicit transaction, SQL Server has to start one internally for me so that there&#8217;s a boundary for where to rollback if something goes wrong during the operation.<\/p>\n<p style=\"text-align: justify;\">And now an update operation (with a checkpoint first to clear out the log):<\/p>\n<pre class=\"brush: sql; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nCHECKPOINT;\r\nGO\r\nUPDATE LockLogTest SET c1 = 3;\r\nGO\r\nSELECT &#x5B;Operation], &#x5B;Context], &#x5B;Page ID], &#x5B;Slot ID], &#x5B;Number of Locks] AS Locks, &#x5B;Lock Information]\r\nFROM fn_dblog (NULL, NULL);\r\nGO\r\n<\/pre>\n<pre class=\"brush: plain; gutter: false; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nOperation        Context       Page ID        Slot ID  Locks Lock Information\r\n---------------- ------------- -------------- -------- ----- -------------------------------------------------------------------------------------------------------\r\nLOP_BEGIN_XACT   LCX_NULL      NULL           NULL     NULL  NULL\r\nLOP_MODIFY_ROW   LCX_HEAP      0001:0000009a  0        3     ACQUIRE_LOCK_IX OBJECT: 18:2073058421:0;ACQUIRE_LOCK_IX PAGE: 18:1:154; ACQUIRE_LOCK_X RID: 18:1:154:0\r\nLOP_MODIFY_ROW   LCX_HEAP      0001:0000009a  1        3     ACQUIRE_LOCK_IX OBJECT: 18:2073058421:0;ACQUIRE_LOCK_IX PAGE: 18:1:154; ACQUIRE_LOCK_X RID: 18:1:154:1\r\nLOP_COMMIT_XACT  LCX_NULL      NULL           NULL     NULL  NULL\r\n<\/pre>\n<p style=\"text-align: justify;\">Just as we expected &#8211; a\u00a0table IX lock, a page IX lock, and two row X locks on that page.<\/p>\n<p style=\"text-align: justify;\">Now, what about something more complicated like a <em>TRUNCATE TABLE<\/em>? Have you heard the myth about it not being logged? Right &#8211; it&#8217;s a myth:<\/p>\n<pre class=\"brush: sql; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nCHECKPOINT;\r\nGO\r\nTRUNCATE TABLE LockLogTest;\r\nGO\r\nSELECT &#x5B;Operation], &#x5B;Context], &#x5B;Page ID], &#x5B;Slot ID], &#x5B;Number of Locks] AS Locks, &#x5B;Lock Information]\r\nFROM fn_dblog (NULL, NULL);\r\nGO\r\n<\/pre>\n<pre class=\"brush: plain; gutter: false; title: ; toolbar: true; wrap-lines: true; notranslate\" title=\"\">\r\nOperation        Context       Page ID        Slot ID  Locks Lock Information\r\n---------------- ------------- -------------- -------- ----- ----------------------------------------------------------------------------\r\nLOP_BEGIN_XACT   LCX_NULL      NULL           NULL     NULL  NULL\r\nLOP_LOCK_XACT    LCX_NULL      NULL           NULL     1     ACQUIRE_LOCK_SCH_M OBJECT: 18:2073058421:0\r\nLOP_MODIFY_ROW   LCX_IAM       0001:0000009b  0        1     ACQUIRE_LOCK_X RID: 18:1:155:0\r\nLOP_MODIFY_ROW   LCX_PFS       0001:00000001  0        1     ACQUIRE_LOCK_X PAGE: 18:1:154\r\nLOP_MODIFY_ROW   LCX_PFS       0001:00000001  0        1     ACQUIRE_LOCK_X PAGE: 18:1:155\r\nLOP_MODIFY_ROW   LCX_IAM       0001:00000099  0        1     ACQUIRE_LOCK_X RID: 18:1:153:0\r\nLOP_MODIFY_ROW   LCX_PFS       0001:00000001  0        1     ACQUIRE_LOCK_X PAGE: 18:1:152\r\nLOP_MODIFY_ROW   LCX_PFS       0001:00000001  0        1     ACQUIRE_LOCK_X PAGE: 18:1:153\r\nLOP_SET_BITS     LCX_SGAM      0001:00000003  1        NULL  NULL\r\nLOP_SET_BITS     LCX_GAM       0001:00000002  1        NULL  NULL\r\nLOP_COUNT_DELTA  LCX_CLUSTERED 0001:00000014  89       NULL  NULL\r\nLOP_COUNT_DELTA  LCX_CLUSTERED 0001:00000011  78       NULL  NULL\r\nLOP_COUNT_DELTA  LCX_CLUSTERED 0001:00000014  90       NULL  NULL\r\nLOP_COUNT_DELTA  LCX_CLUSTERED 0001:00000041  164      NULL  NULL\r\nLOP_COUNT_DELTA  LCX_CLUSTERED 0001:00000041  165      NULL  NULL\r\nLOP_COUNT_DELTA  LCX_CLUSTERED 0001:00000041  166      NULL  NULL\r\nLOP_HOBT_DDL     LCX_NULL      NULL           NULL     NULL  NULL\r\nLOP_MODIFY_ROW   LCX_CLUSTERED 0001:00000014  89       2     ACQUIRE_LOCK_IX OBJECT: 18:7:0;ACQUIRE_LOCK_X KEY: 18:458752 (0000c2681664)\r\nLOP_HOBT_DDL     LCX_NULL      NULL           NULL     NULL  NULL\r\nLOP_MODIFY_ROW   LCX_CLUSTERED 0001:00000014  90       2     ACQUIRE_LOCK_IX OBJECT: 18:7:0;ACQUIRE_LOCK_X KEY: 18:458752 (00007a581379)\r\nLOP_MODIFY_ROW   LCX_CLUSTERED 0001:00000011  78       2     ACQUIRE_LOCK_IX OBJECT: 18:5:0;ACQUIRE_LOCK_X KEY: 18:327680 (00001df3833b)\r\nLOP_COMMIT_XACT  LCX_NULL      NULL           NULL     NULL  NULL\r\n<\/pre>\n<p style=\"text-align: justify;\">Lots of logging and lots of locks. If you look at the <em>Context<\/em> column, you&#8217;ll see that the operation is modifying allocation bitmaps (<em>LCX_IAM<\/em>, <em>LCX_PFS<\/em>, <em>LCX_SGAM<\/em>, <em>LCX_GAM<\/em>) but taking locks on the table pages, not on the allocation bitmaps themselves &#8211; they&#8217;re only ever <em>latched<\/em> (an internal, much lighter-weight, synchronization mechanism). This is done as the pages comprising the table are deallocated &#8211; this is all done because the table&#8217;s small enough that the Storage Engine chooses to deallocate all the storage immediately, instead of pushing it all onto the task queue for the deferred drop background task. See my previous post <em><a href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-10-when-are-pages-from-a-truncated-table-reused\/\">Search Engine Q&amp;A #10: When are pages from a truncated table reused?<\/a><\/em>\u00a0which discusses this too.<\/p>\n<p style=\"text-align: justify;\">There are no actual row operations performed on the table itself. The only table row operations are down at the bottom on table with object IDs 7 and 5 (<em>sys.sysallocunits<\/em> and <em>sys.sysrowsets<\/em>, respectively) to update the page counts, first IAM, and first page entries for the table.<\/p>\n<p style=\"text-align: justify;\">So &#8211; hopefully this has been useful to you. In the next post in the series, I&#8217;ll discuss compensation log records and how rollback operations work.<\/p>\n<p style=\"text-align: justify;\">PS Send me an email or put in a comment if there&#8217;s something in particular about the log (or log records) you&#8217;d like to see explained.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the things I love teaching is how the transaction log and logging\/recovery work. I presented a session on this at both PASS and SQL Connections in the last two weeks, and in both sessions I promised to write some blog posts about the deep internals of logging operations. This is the first one [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48,57,62,98],"tags":[],"class_list":["post-771","post","type-post","status-publish","format-standard","hentry","category-inside-the-storage-engine","category-locking","category-on-disk-structures","category-transaction-log"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Lock logging and fast recovery - Paul S. Randal<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Lock logging and fast recovery - Paul S. Randal\" \/>\n<meta property=\"og:description\" content=\"One of the things I love teaching is how the transaction log and logging\/recovery work. I presented a session on this at both PASS and SQL Connections in the last two weeks, and in both sessions I promised to write some blog posts about the deep internals of logging operations. This is the first one [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/\" \/>\n<meta property=\"og:site_name\" content=\"Paul S. Randal\" \/>\n<meta property=\"article:published_time\" content=\"2009-11-13T13:24:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-08-11T17:24:01+00:00\" \/>\n<meta name=\"author\" content=\"Paul Randal\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Paul Randal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/\",\"name\":\"Lock logging and fast recovery - Paul S. Randal\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#website\"},\"datePublished\":\"2009-11-13T13:24:00+00:00\",\"dateModified\":\"2017-08-11T17:24:01+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Lock logging and fast recovery\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/\",\"name\":\"Paul S. Randal\",\"description\":\"In Recovery...\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce\",\"name\":\"Paul Randal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g\",\"caption\":\"Paul Randal\"},\"sameAs\":[\"http:\/\/3.209.169.194\/blogs\/paul\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/author\/paul\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Lock logging and fast recovery - Paul S. Randal","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/","og_locale":"en_US","og_type":"article","og_title":"Lock logging and fast recovery - Paul S. Randal","og_description":"One of the things I love teaching is how the transaction log and logging\/recovery work. I presented a session on this at both PASS and SQL Connections in the last two weeks, and in both sessions I promised to write some blog posts about the deep internals of logging operations. This is the first one [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/","og_site_name":"Paul S. Randal","article_published_time":"2009-11-13T13:24:00+00:00","article_modified_time":"2017-08-11T17:24:01+00:00","author":"Paul Randal","twitter_misc":{"Written by":"Paul Randal","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/","url":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/","name":"Lock logging and fast recovery - Paul S. Randal","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#website"},"datePublished":"2009-11-13T13:24:00+00:00","dateModified":"2017-08-11T17:24:01+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/lock-logging-and-fast-recovery\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/paul\/"},{"@type":"ListItem","position":2,"name":"Lock logging and fast recovery"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/paul\/","name":"Paul S. Randal","description":"In Recovery...","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/paul\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce","name":"Paul Randal","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g","caption":"Paul Randal"},"sameAs":["http:\/\/3.209.169.194\/blogs\/paul"],"url":"https:\/\/www.sqlskills.com\/blogs\/paul\/author\/paul\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/posts\/771","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/comments?post=771"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/posts\/771\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/media?parent=771"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/categories?post=771"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/tags?post=771"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}