Чому цей замок RX-X не відображається в розширених подіях?


13

Проблема

У мене є пара запитів, які під час серіалізаційної ізоляції викликають блокування RX-X. Однак, коли я використовую розширені події для перегляду придбання блокування, придбання блокування RX-X ніколи не з'являється, воно лише випускається. Звідки воно походить?

Репро

Ось мій стіл:

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')

Ось мій пакет проблем:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

INSERT dbo.LockTest
VALUES ('bleh')

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

--ROLLBACK

Я перевіряю блокування, проведені цим сеансом, і бачу 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

Але я також маю розширений захід на lock_acquiredта lock_released. Я фільтрую його за відповідним асоційованим_об'єктом_id ... RX-X немає.

Розширений вихід подій

Після виконання відкату я бачу, що RX-X (LAST_MODE) звільнений, хоча він ніколи не був придбаний.

LAST_MODE

Що я пробував

  • Я переглянув усі замки в розширених подіях - відсутня фільтрація. Не придбано замок RX-X.

  • Я також спробував Profiler: ті ж результати (за винятком, звичайно, він отримує назву правильно ... немає "LAST_MODE").

  • Я запустив XE для ескалації блокування - його там немає.

  • Спеціально для конверсій XE немає, але я зміг підтвердити, що принаймні перетворення блокування U - X фіксує lock_acquired

Також слід зазначити, що RI-N отримує, але ніколи не випускається. Моя поточна гіпотеза полягає в тому, що RX-X є блоком перетворення, як описано тут . У моїй партії є блоки, що перекриваються між собою, які виглядають так, що вони мають право на конверсію, але замок RX-X відсутній у таблиці перетворення.

Звідки береться цей замок і чому його не підхоплюють розширені події?

Відповіді:


12

Вставка одного рядка набуває X(ексклюзивний) замок у новому рядку.

Ці SELECTспроби придбати діапазон спільно використовуваний ключ, загальні ( RangeS-S) блокування.

lock_acquiredРозширена подія повідомляє про цей запит як режим = RS_S.

Про це повідомляється класом подій Profiler Lock:Acquiredяк режим 13 ( LCK_M_RS_S).

Запитаний режим поєднується з існуючим ексклюзивним режимом блокування Lock::CalculateGrantModeв sqlmin.dll. Не існує комбінованого режиму розділеного діапазону, виключення ключів ( RangeS-X), тому результат обчислення є виключним діапазоном, ключовим ексклюзивом ( RangeX-X), що відбувається у режимі 15.

Розрахунок режиму дотації вище виконується безпосередньо перед тим, як генерується розширена подія lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Тим не менше, і Profiler, і розширені події записують запитуваний RangeS-S режим, а не результат блокування RangeX-X. Це суперечить обмеженій документації , яка говорить:

Режим | int | Результатний режим після придбання блокування.

У стовпці режиму розгорнутої події взагалі немає документації, а опис у метаданих порожній. Можливо, самі Microsoft навіть не були впевнені у своїй поведінці.

Я часто думав, що було б корисніше, якби події блокування повідомляли про запитуваний і результуючий режими, але це не те, що ми маємо. Поточна домовленість робить неможливим відстежувати та узгоджувати придбання та випуск блокування.

Там може бути хорошим приводом для подання замки таким чином. Якщо це не відповідає вашим потребам, ви можете відкрити службу підтримки у Microsoft або створити елемент відгуку Azure.


LAST_MODE

Таємниче LAST_MODE- це те, про що раніше зауважував Ерік Дарлінг . Це найвище map_keyзначення у списку режимів блокування, які піддаються 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 ║
╚═════════╩═══════════╝

Структура пам'яті, доступ до якої здійснюється за допомогою DMV (за допомогою sqlmin!CMapValuesTable), зберігається починаючи з адреси sqlmin!XeSqlPkg::g_lock_mode. Кожен 16-байтний запис у структурі містить map_keyрядок та вказівник на рядок, повернутий як map_valueпотоковий TVF.

Рядки зберігаються точно так, як показано в таблиці вище (хоча не в тому порядку). Здається, помилка в тому, що в записі 21 є map_value"LAST_MODE" замість очікуваного "RX_X". Ерік Дарлінг повідомив про проблему в Azure Feedback .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.