Why does this RX-X lock not appear in Extended Events?Is there a more helpful way to detect lock acquire/release stats in SQL Profiler?Synchronize Queries Retrieving Sessions And Locks From DMVsHold exclusive lock on a whole DBCan I rely on reading SQL Server Identity values in order?What interval does SQL Server Profiler's “duration” refer to?Extended Events filteringExtended event for lock count does not show locksWhy adding FOREIGN KEY constraint does not lock the tableSQL Server Exclusive(X) lock not consistently blocking Shared(S) lock on a resourceWhy does an UPDATE to a full-text-indexed column lock the full text index?

Is The Lion King live action film made in motion capture?

Double blind peer review when paper cites author's GitHub repo for code

Blocking people from taking pictures of me with smartphone

As a 16 year old, how can I keep my money safe from my mother?

Is it really ~648.69 km/s delta-v to "land" on the surface of the Sun?

Improving software when the author can see no need for improvement

Sierpinski turtle triangle

Is it true that control+alt+delete only became a thing because IBM would not build Bill Gates a computer with a task manager button?

Acceptable to cut steak before searing?

Does a code snippet compile? Or does it gets compiled?

What is the best way to cause swarm intelligence to be destroyed?

Why does Intel's Haswell chip allow multiplication to be twice as fast as addition?

Can I call myself an assistant professor without a PhD

Are any jet engines used in combat aircraft water cooled?

Replace data between quotes in a file

How to precisely measure small charges?

Why should we care about syntactic proofs if we can show semantically that statements are true?

In a topological space if there exists a loop that cannot be contracted to a point does there exist a simple loop that cannot be contracted also?

How can glass marbles naturally occur in a desert?

How do we avoid CI-driven development...?

How to display a duet in lyrics?

sed delete all the words before a match

Is there a loss of quality when converting RGB to HEX?

Ordering a word list



Why does this RX-X lock not appear in Extended Events?


Is there a more helpful way to detect lock acquire/release stats in SQL Profiler?Synchronize Queries Retrieving Sessions And Locks From DMVsHold exclusive lock on a whole DBCan I rely on reading SQL Server Identity values in order?What interval does SQL Server Profiler's “duration” refer to?Extended Events filteringExtended event for lock count does not show locksWhy adding FOREIGN KEY constraint does not lock the tableSQL Server Exclusive(X) lock not consistently blocking Shared(S) lock on a resourceWhy does an UPDATE to a full-text-indexed column lock the full text index?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








13















The Problem



I have a pair of queries that, under serializable isolation, cause an RX-X lock. However, when I use Extended Events to watch lock acquisition, the RX-X lock acquisition never appears, it is only released. Where does it come from?



The Repro



Here's my table:



CREATE TABLE dbo.LockTest (
ID int identity,
Junk char(4)
)

CREATE CLUSTERED INDEX CX_LockTest --not unique!
ON dbo.LockTest(ID)

--preload some rows
INSERT dbo.LockTest
VALUES ('data'),('data'),('data')


Here's my problem batch:



SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

INSERT dbo.LockTest
VALUES ('bleh')

SELECT *
FROM dbo.LockTest
WHERE ID = SCOPE_IDENTITY()

--ROLLBACK


I check locks held by this session, and see RX-X:



SELECT resource_type, request_mode, request_status, resource_description
FROM sys.dm_tran_locks
WHERE request_session_id = 72 --change SPID!


dm_tran_locks



But I also have an Extended Event on lock_acquired and lock_released. I filter it on the appropriate associated_object_id...there's no RX-X.



Extended Event output



After executing the rollback, I see RX-X (LAST_MODE) released, even though it was never acquired.



LAST_MODE



What I've Tried



  • I looked at all locks in Extended Events - no filtering. No RX-X locks acquired.


  • I also tried Profiler: same results (except of course it gets the name right...no "LAST_MODE").


  • I ran the XE for lock escalations - it's not there.


  • There's no XE specifically for conversions, but I was able to confirm that at least the U to X lock conversion is captured by lock_acquired


Also of note is the RI-N that gets acquired but never released. My current hypothesis is that the RX-X is a conversion lock, as described here. There are overlapping key-range locks in my batch that look like they should qualify for conversion, but the RX-X lock isn't in the conversion table.



Where is this lock coming from, and why isn't it picked up by Extended Events?










share|improve this question






























    13















    The Problem



    I have a pair of queries that, under serializable isolation, cause an RX-X lock. However, when I use Extended Events to watch lock acquisition, the RX-X lock acquisition never appears, it is only released. Where does it come from?



    The Repro



    Here's my table:



    CREATE TABLE dbo.LockTest (
    ID int identity,
    Junk char(4)
    )

    CREATE CLUSTERED INDEX CX_LockTest --not unique!
    ON dbo.LockTest(ID)

    --preload some rows
    INSERT dbo.LockTest
    VALUES ('data'),('data'),('data')


    Here's my problem batch:



    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

    BEGIN TRAN

    INSERT dbo.LockTest
    VALUES ('bleh')

    SELECT *
    FROM dbo.LockTest
    WHERE ID = SCOPE_IDENTITY()

    --ROLLBACK


    I check locks held by this session, and see RX-X:



    SELECT resource_type, request_mode, request_status, resource_description
    FROM sys.dm_tran_locks
    WHERE request_session_id = 72 --change SPID!


    dm_tran_locks



    But I also have an Extended Event on lock_acquired and lock_released. I filter it on the appropriate associated_object_id...there's no RX-X.



    Extended Event output



    After executing the rollback, I see RX-X (LAST_MODE) released, even though it was never acquired.



    LAST_MODE



    What I've Tried



    • I looked at all locks in Extended Events - no filtering. No RX-X locks acquired.


    • I also tried Profiler: same results (except of course it gets the name right...no "LAST_MODE").


    • I ran the XE for lock escalations - it's not there.


    • There's no XE specifically for conversions, but I was able to confirm that at least the U to X lock conversion is captured by lock_acquired


    Also of note is the RI-N that gets acquired but never released. My current hypothesis is that the RX-X is a conversion lock, as described here. There are overlapping key-range locks in my batch that look like they should qualify for conversion, but the RX-X lock isn't in the conversion table.



    Where is this lock coming from, and why isn't it picked up by Extended Events?










    share|improve this question


























      13












      13








      13


      0






      The Problem



      I have a pair of queries that, under serializable isolation, cause an RX-X lock. However, when I use Extended Events to watch lock acquisition, the RX-X lock acquisition never appears, it is only released. Where does it come from?



      The Repro



      Here's my table:



      CREATE TABLE dbo.LockTest (
      ID int identity,
      Junk char(4)
      )

      CREATE CLUSTERED INDEX CX_LockTest --not unique!
      ON dbo.LockTest(ID)

      --preload some rows
      INSERT dbo.LockTest
      VALUES ('data'),('data'),('data')


      Here's my problem batch:



      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

      BEGIN TRAN

      INSERT dbo.LockTest
      VALUES ('bleh')

      SELECT *
      FROM dbo.LockTest
      WHERE ID = SCOPE_IDENTITY()

      --ROLLBACK


      I check locks held by this session, and see RX-X:



      SELECT resource_type, request_mode, request_status, resource_description
      FROM sys.dm_tran_locks
      WHERE request_session_id = 72 --change SPID!


      dm_tran_locks



      But I also have an Extended Event on lock_acquired and lock_released. I filter it on the appropriate associated_object_id...there's no RX-X.



      Extended Event output



      After executing the rollback, I see RX-X (LAST_MODE) released, even though it was never acquired.



      LAST_MODE



      What I've Tried



      • I looked at all locks in Extended Events - no filtering. No RX-X locks acquired.


      • I also tried Profiler: same results (except of course it gets the name right...no "LAST_MODE").


      • I ran the XE for lock escalations - it's not there.


      • There's no XE specifically for conversions, but I was able to confirm that at least the U to X lock conversion is captured by lock_acquired


      Also of note is the RI-N that gets acquired but never released. My current hypothesis is that the RX-X is a conversion lock, as described here. There are overlapping key-range locks in my batch that look like they should qualify for conversion, but the RX-X lock isn't in the conversion table.



      Where is this lock coming from, and why isn't it picked up by Extended Events?










      share|improve this question














      The Problem



      I have a pair of queries that, under serializable isolation, cause an RX-X lock. However, when I use Extended Events to watch lock acquisition, the RX-X lock acquisition never appears, it is only released. Where does it come from?



      The Repro



      Here's my table:



      CREATE TABLE dbo.LockTest (
      ID int identity,
      Junk char(4)
      )

      CREATE CLUSTERED INDEX CX_LockTest --not unique!
      ON dbo.LockTest(ID)

      --preload some rows
      INSERT dbo.LockTest
      VALUES ('data'),('data'),('data')


      Here's my problem batch:



      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

      BEGIN TRAN

      INSERT dbo.LockTest
      VALUES ('bleh')

      SELECT *
      FROM dbo.LockTest
      WHERE ID = SCOPE_IDENTITY()

      --ROLLBACK


      I check locks held by this session, and see RX-X:



      SELECT resource_type, request_mode, request_status, resource_description
      FROM sys.dm_tran_locks
      WHERE request_session_id = 72 --change SPID!


      dm_tran_locks



      But I also have an Extended Event on lock_acquired and lock_released. I filter it on the appropriate associated_object_id...there's no RX-X.



      Extended Event output



      After executing the rollback, I see RX-X (LAST_MODE) released, even though it was never acquired.



      LAST_MODE



      What I've Tried



      • I looked at all locks in Extended Events - no filtering. No RX-X locks acquired.


      • I also tried Profiler: same results (except of course it gets the name right...no "LAST_MODE").


      • I ran the XE for lock escalations - it's not there.


      • There's no XE specifically for conversions, but I was able to confirm that at least the U to X lock conversion is captured by lock_acquired


      Also of note is the RI-N that gets acquired but never released. My current hypothesis is that the RX-X is a conversion lock, as described here. There are overlapping key-range locks in my batch that look like they should qualify for conversion, but the RX-X lock isn't in the conversion table.



      Where is this lock coming from, and why isn't it picked up by Extended Events?







      sql-server locking sql-server-2017






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jul 29 at 16:20









      ForrestForrest

      3,2361 gold badge9 silver badges27 bronze badges




      3,2361 gold badge9 silver badges27 bronze badges























          1 Answer
          1






          active

          oldest

          votes


















          11














          The single row insert acquires an X (exclusive) lock on the new row.



          The SELECT attempts to acquire a range-shared, key shared (RangeS-S) lock.



          This request is reported by the lock_acquired Extended Event as mode = RS_S.



          It is reported by the Profiler event class Lock:Acquired as mode 13 (LCK_M_RS_S).



          The requested mode is combined with the existing exclusive lock mode in Lock::CalculateGrantMode in sqlmin.dll. There is no combined mode of range-shared, key exclusive (RangeS-X) so the outcome of the calculation is range-exclusive, key exclusive (RangeX-X), which happens to be mode 15.



          The grant mode calculation above is performed just before the extended event is generated by lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Nevertheless, both Profiler and Extended Events log the requested RangeS-S mode, not the resulting lock mode RangeX-X. This is counter to the limited documentation, which says:




          Mode | int | Resulting mode after the lock was acquired.




          The mode column of the extended event has no documentation at all, and the description in the meta data is blank. Perhaps Microsoft themselves weren't even sure of the behaviour.



          I have often thought it would be more useful if lock events reported both the requested and resulting modes, but that is not what we have. The current arrangement makes it pretty much impossible to track and match up lock acquisition and release.



          There might be a good reason for reporting locks this way. If it doesn't meet your needs, you could open a support case with Microsoft, or create an Azure Feedback item.




          LAST_MODE



          The mysterious LAST_MODE is something Erik Darling has remarked on before. It is the highest map_key value in the list of lock modes exposed by sys.dm_xe_map_values:



          SELECT
          DXMV.map_key,
          DXMV.map_value
          FROM sys.dm_xe_map_values AS DXMV
          WHERE
          DXMV.[name] = N'lock_mode'
          ORDER BY
          DXMV.map_key;


          ╔═════════╦═══════════╗
          ║ map_key ║ map_value ║
          ╠═════════╬═══════════╣
          ║ 0 ║ NL ║
          ║ 1 ║ SCH_S ║
          ║ 2 ║ SCH_M ║
          ║ 3 ║ S ║
          ║ 4 ║ U ║
          ║ 5 ║ X ║
          ║ 6 ║ IS ║
          ║ 7 ║ IU ║
          ║ 8 ║ IX ║
          ║ 9 ║ SIU ║
          ║ 10 ║ SIX ║
          ║ 11 ║ UIX ║
          ║ 12 ║ BU ║
          ║ 13 ║ RS_S ║
          ║ 14 ║ RS_U ║
          ║ 15 ║ RI_NL ║
          ║ 16 ║ RI_S ║
          ║ 17 ║ RI_U ║
          ║ 18 ║ RI_X ║
          ║ 19 ║ RX_S ║
          ║ 20 ║ RX_U ║
          ║ 21 ║ LAST_MODE ║
          ╚═════════╩═══════════╝


          The memory structure accessed via the DMV (using sqlmin!CMapValuesTable) is stored starting at the address sqlmin!XeSqlPkg::g_lock_mode. Each 16-byte entry in the structure contains the map_key and a pointer to the string returned as map_value by the streaming TVF.



          The strings are stored exactly as shown in the table above (though not in that order). It seems to be an error that entry 21 has a map_value of "LAST_MODE" instead of the expected "RX_X".






          share|improve this answer





























            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "182"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f244054%2fwhy-does-this-rx-x-lock-not-appear-in-extended-events%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            11














            The single row insert acquires an X (exclusive) lock on the new row.



            The SELECT attempts to acquire a range-shared, key shared (RangeS-S) lock.



            This request is reported by the lock_acquired Extended Event as mode = RS_S.



            It is reported by the Profiler event class Lock:Acquired as mode 13 (LCK_M_RS_S).



            The requested mode is combined with the existing exclusive lock mode in Lock::CalculateGrantMode in sqlmin.dll. There is no combined mode of range-shared, key exclusive (RangeS-X) so the outcome of the calculation is range-exclusive, key exclusive (RangeX-X), which happens to be mode 15.



            The grant mode calculation above is performed just before the extended event is generated by lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Nevertheless, both Profiler and Extended Events log the requested RangeS-S mode, not the resulting lock mode RangeX-X. This is counter to the limited documentation, which says:




            Mode | int | Resulting mode after the lock was acquired.




            The mode column of the extended event has no documentation at all, and the description in the meta data is blank. Perhaps Microsoft themselves weren't even sure of the behaviour.



            I have often thought it would be more useful if lock events reported both the requested and resulting modes, but that is not what we have. The current arrangement makes it pretty much impossible to track and match up lock acquisition and release.



            There might be a good reason for reporting locks this way. If it doesn't meet your needs, you could open a support case with Microsoft, or create an Azure Feedback item.




            LAST_MODE



            The mysterious LAST_MODE is something Erik Darling has remarked on before. It is the highest map_key value in the list of lock modes exposed by sys.dm_xe_map_values:



            SELECT
            DXMV.map_key,
            DXMV.map_value
            FROM sys.dm_xe_map_values AS DXMV
            WHERE
            DXMV.[name] = N'lock_mode'
            ORDER BY
            DXMV.map_key;


            ╔═════════╦═══════════╗
            ║ map_key ║ map_value ║
            ╠═════════╬═══════════╣
            ║ 0 ║ NL ║
            ║ 1 ║ SCH_S ║
            ║ 2 ║ SCH_M ║
            ║ 3 ║ S ║
            ║ 4 ║ U ║
            ║ 5 ║ X ║
            ║ 6 ║ IS ║
            ║ 7 ║ IU ║
            ║ 8 ║ IX ║
            ║ 9 ║ SIU ║
            ║ 10 ║ SIX ║
            ║ 11 ║ UIX ║
            ║ 12 ║ BU ║
            ║ 13 ║ RS_S ║
            ║ 14 ║ RS_U ║
            ║ 15 ║ RI_NL ║
            ║ 16 ║ RI_S ║
            ║ 17 ║ RI_U ║
            ║ 18 ║ RI_X ║
            ║ 19 ║ RX_S ║
            ║ 20 ║ RX_U ║
            ║ 21 ║ LAST_MODE ║
            ╚═════════╩═══════════╝


            The memory structure accessed via the DMV (using sqlmin!CMapValuesTable) is stored starting at the address sqlmin!XeSqlPkg::g_lock_mode. Each 16-byte entry in the structure contains the map_key and a pointer to the string returned as map_value by the streaming TVF.



            The strings are stored exactly as shown in the table above (though not in that order). It seems to be an error that entry 21 has a map_value of "LAST_MODE" instead of the expected "RX_X".






            share|improve this answer































              11














              The single row insert acquires an X (exclusive) lock on the new row.



              The SELECT attempts to acquire a range-shared, key shared (RangeS-S) lock.



              This request is reported by the lock_acquired Extended Event as mode = RS_S.



              It is reported by the Profiler event class Lock:Acquired as mode 13 (LCK_M_RS_S).



              The requested mode is combined with the existing exclusive lock mode in Lock::CalculateGrantMode in sqlmin.dll. There is no combined mode of range-shared, key exclusive (RangeS-X) so the outcome of the calculation is range-exclusive, key exclusive (RangeX-X), which happens to be mode 15.



              The grant mode calculation above is performed just before the extended event is generated by lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Nevertheless, both Profiler and Extended Events log the requested RangeS-S mode, not the resulting lock mode RangeX-X. This is counter to the limited documentation, which says:




              Mode | int | Resulting mode after the lock was acquired.




              The mode column of the extended event has no documentation at all, and the description in the meta data is blank. Perhaps Microsoft themselves weren't even sure of the behaviour.



              I have often thought it would be more useful if lock events reported both the requested and resulting modes, but that is not what we have. The current arrangement makes it pretty much impossible to track and match up lock acquisition and release.



              There might be a good reason for reporting locks this way. If it doesn't meet your needs, you could open a support case with Microsoft, or create an Azure Feedback item.




              LAST_MODE



              The mysterious LAST_MODE is something Erik Darling has remarked on before. It is the highest map_key value in the list of lock modes exposed by sys.dm_xe_map_values:



              SELECT
              DXMV.map_key,
              DXMV.map_value
              FROM sys.dm_xe_map_values AS DXMV
              WHERE
              DXMV.[name] = N'lock_mode'
              ORDER BY
              DXMV.map_key;


              ╔═════════╦═══════════╗
              ║ map_key ║ map_value ║
              ╠═════════╬═══════════╣
              ║ 0 ║ NL ║
              ║ 1 ║ SCH_S ║
              ║ 2 ║ SCH_M ║
              ║ 3 ║ S ║
              ║ 4 ║ U ║
              ║ 5 ║ X ║
              ║ 6 ║ IS ║
              ║ 7 ║ IU ║
              ║ 8 ║ IX ║
              ║ 9 ║ SIU ║
              ║ 10 ║ SIX ║
              ║ 11 ║ UIX ║
              ║ 12 ║ BU ║
              ║ 13 ║ RS_S ║
              ║ 14 ║ RS_U ║
              ║ 15 ║ RI_NL ║
              ║ 16 ║ RI_S ║
              ║ 17 ║ RI_U ║
              ║ 18 ║ RI_X ║
              ║ 19 ║ RX_S ║
              ║ 20 ║ RX_U ║
              ║ 21 ║ LAST_MODE ║
              ╚═════════╩═══════════╝


              The memory structure accessed via the DMV (using sqlmin!CMapValuesTable) is stored starting at the address sqlmin!XeSqlPkg::g_lock_mode. Each 16-byte entry in the structure contains the map_key and a pointer to the string returned as map_value by the streaming TVF.



              The strings are stored exactly as shown in the table above (though not in that order). It seems to be an error that entry 21 has a map_value of "LAST_MODE" instead of the expected "RX_X".






              share|improve this answer





























                11












                11








                11







                The single row insert acquires an X (exclusive) lock on the new row.



                The SELECT attempts to acquire a range-shared, key shared (RangeS-S) lock.



                This request is reported by the lock_acquired Extended Event as mode = RS_S.



                It is reported by the Profiler event class Lock:Acquired as mode 13 (LCK_M_RS_S).



                The requested mode is combined with the existing exclusive lock mode in Lock::CalculateGrantMode in sqlmin.dll. There is no combined mode of range-shared, key exclusive (RangeS-X) so the outcome of the calculation is range-exclusive, key exclusive (RangeX-X), which happens to be mode 15.



                The grant mode calculation above is performed just before the extended event is generated by lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Nevertheless, both Profiler and Extended Events log the requested RangeS-S mode, not the resulting lock mode RangeX-X. This is counter to the limited documentation, which says:




                Mode | int | Resulting mode after the lock was acquired.




                The mode column of the extended event has no documentation at all, and the description in the meta data is blank. Perhaps Microsoft themselves weren't even sure of the behaviour.



                I have often thought it would be more useful if lock events reported both the requested and resulting modes, but that is not what we have. The current arrangement makes it pretty much impossible to track and match up lock acquisition and release.



                There might be a good reason for reporting locks this way. If it doesn't meet your needs, you could open a support case with Microsoft, or create an Azure Feedback item.




                LAST_MODE



                The mysterious LAST_MODE is something Erik Darling has remarked on before. It is the highest map_key value in the list of lock modes exposed by sys.dm_xe_map_values:



                SELECT
                DXMV.map_key,
                DXMV.map_value
                FROM sys.dm_xe_map_values AS DXMV
                WHERE
                DXMV.[name] = N'lock_mode'
                ORDER BY
                DXMV.map_key;


                ╔═════════╦═══════════╗
                ║ map_key ║ map_value ║
                ╠═════════╬═══════════╣
                ║ 0 ║ NL ║
                ║ 1 ║ SCH_S ║
                ║ 2 ║ SCH_M ║
                ║ 3 ║ S ║
                ║ 4 ║ U ║
                ║ 5 ║ X ║
                ║ 6 ║ IS ║
                ║ 7 ║ IU ║
                ║ 8 ║ IX ║
                ║ 9 ║ SIU ║
                ║ 10 ║ SIX ║
                ║ 11 ║ UIX ║
                ║ 12 ║ BU ║
                ║ 13 ║ RS_S ║
                ║ 14 ║ RS_U ║
                ║ 15 ║ RI_NL ║
                ║ 16 ║ RI_S ║
                ║ 17 ║ RI_U ║
                ║ 18 ║ RI_X ║
                ║ 19 ║ RX_S ║
                ║ 20 ║ RX_U ║
                ║ 21 ║ LAST_MODE ║
                ╚═════════╩═══════════╝


                The memory structure accessed via the DMV (using sqlmin!CMapValuesTable) is stored starting at the address sqlmin!XeSqlPkg::g_lock_mode. Each 16-byte entry in the structure contains the map_key and a pointer to the string returned as map_value by the streaming TVF.



                The strings are stored exactly as shown in the table above (though not in that order). It seems to be an error that entry 21 has a map_value of "LAST_MODE" instead of the expected "RX_X".






                share|improve this answer















                The single row insert acquires an X (exclusive) lock on the new row.



                The SELECT attempts to acquire a range-shared, key shared (RangeS-S) lock.



                This request is reported by the lock_acquired Extended Event as mode = RS_S.



                It is reported by the Profiler event class Lock:Acquired as mode 13 (LCK_M_RS_S).



                The requested mode is combined with the existing exclusive lock mode in Lock::CalculateGrantMode in sqlmin.dll. There is no combined mode of range-shared, key exclusive (RangeS-X) so the outcome of the calculation is range-exclusive, key exclusive (RangeX-X), which happens to be mode 15.



                The grant mode calculation above is performed just before the extended event is generated by lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Nevertheless, both Profiler and Extended Events log the requested RangeS-S mode, not the resulting lock mode RangeX-X. This is counter to the limited documentation, which says:




                Mode | int | Resulting mode after the lock was acquired.




                The mode column of the extended event has no documentation at all, and the description in the meta data is blank. Perhaps Microsoft themselves weren't even sure of the behaviour.



                I have often thought it would be more useful if lock events reported both the requested and resulting modes, but that is not what we have. The current arrangement makes it pretty much impossible to track and match up lock acquisition and release.



                There might be a good reason for reporting locks this way. If it doesn't meet your needs, you could open a support case with Microsoft, or create an Azure Feedback item.




                LAST_MODE



                The mysterious LAST_MODE is something Erik Darling has remarked on before. It is the highest map_key value in the list of lock modes exposed by sys.dm_xe_map_values:



                SELECT
                DXMV.map_key,
                DXMV.map_value
                FROM sys.dm_xe_map_values AS DXMV
                WHERE
                DXMV.[name] = N'lock_mode'
                ORDER BY
                DXMV.map_key;


                ╔═════════╦═══════════╗
                ║ map_key ║ map_value ║
                ╠═════════╬═══════════╣
                ║ 0 ║ NL ║
                ║ 1 ║ SCH_S ║
                ║ 2 ║ SCH_M ║
                ║ 3 ║ S ║
                ║ 4 ║ U ║
                ║ 5 ║ X ║
                ║ 6 ║ IS ║
                ║ 7 ║ IU ║
                ║ 8 ║ IX ║
                ║ 9 ║ SIU ║
                ║ 10 ║ SIX ║
                ║ 11 ║ UIX ║
                ║ 12 ║ BU ║
                ║ 13 ║ RS_S ║
                ║ 14 ║ RS_U ║
                ║ 15 ║ RI_NL ║
                ║ 16 ║ RI_S ║
                ║ 17 ║ RI_U ║
                ║ 18 ║ RI_X ║
                ║ 19 ║ RX_S ║
                ║ 20 ║ RX_U ║
                ║ 21 ║ LAST_MODE ║
                ╚═════════╩═══════════╝


                The memory structure accessed via the DMV (using sqlmin!CMapValuesTable) is stored starting at the address sqlmin!XeSqlPkg::g_lock_mode. Each 16-byte entry in the structure contains the map_key and a pointer to the string returned as map_value by the streaming TVF.



                The strings are stored exactly as shown in the table above (though not in that order). It seems to be an error that entry 21 has a map_value of "LAST_MODE" instead of the expected "RX_X".







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jul 31 at 11:10

























                answered Jul 30 at 1:11









                Paul WhitePaul White

                58.3k16 gold badges307 silver badges481 bronze badges




                58.3k16 gold badges307 silver badges481 bronze badges






























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Database Administrators Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f244054%2fwhy-does-this-rx-x-lock-not-appear-in-extended-events%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

                    Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

                    Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form