Почему эта блокировка 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. Я отфильтрую его по соответствующему ассоциированному_объекту ... там нет 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расширенным событием как mode = RS_S.

Класс события Profiler сообщает о нем Lock:Acquiredкак о режиме 13 ( LCK_M_RS_S).

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

Вышеуказанный расчет режима предоставления выполняется непосредственно перед созданием расширенного события lck_ProduceExtendedEvent<XeSqlPkg::lock_acquired>. Тем не менее, и Profiler, и Extended Events регистрируют запрошенный 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.