- •Практическая работа. Бизнес-транзакции и транзакции sql Server
- •Управление изоляцией транзакций
- •Мониторинг блокировок
- •Уровень изоляции транзакции
- •Используем только чтение зафиксированных данных
- •Применяем уровень изоляции read commited
- •Применяем уровень изоляции read commited snapshot
- •Как добиться согласованных повторяющихся операций чтения
- •Применяем уровень изоляции snapshot
- •Как предотвратить параллельные изменения данных
- •Применяем уровень изоляции repeatable read
- •Применяем уровень изоляции serializable
- •Борьба с блокированиями
- •Выполняем мониторинг блокирований при помощи динамических административных представлений
- •Борьба с взаимоблокировками
- •Разыгрываем простой сценарий взаимоблокировки
- •5. Закройте все окна запросов.
Мониторинг блокировок
Чтобы отслеживать блокировки, существующие в базе данных, можно выполнить запрос к динамическому административному представлению sys.dm_tran_locks. Это представление предоставляет строку для каждой отдельной блокировки, существующей в базе данных в настоящий момент.
Запустите SQL Server Management Studio и откройте окно New Query(Новый запрос).
Введите и выполните следующую инструкцию, чтобы запустить транзакцию и выполнить запрос к таблице ПОСТАВЩИКИ. В этой транзакции для того, чтобы инструктировать SQL Server о том, что не надо освобождать блокировку после выполнения инструкции SELECT, используется подсказка блокировки HOLDLOCK. Обратите также внимание на то, что транзакция не фиксируется до тех пор, пока блокировки не будут автоматически освобождены с фиксацией.
USE Ваша_База_Данных;
GO
BEGIN TRAN
SELECT Имя_Поставщика, Статус
FROM Поставщики WITH (HOLDLOCK)
WHERE Код_Поставщика= ‘S5’
3. Чтобы узнать, какие блокировки используются этой транзакцией, можно воспользоваться динамическим административным представлением sys_dm_tran_locks. Чтобы получить сведения только о блокировках, которые принадлежат к конкретной транзакции, можно соединить это представление с другим административным представлением, которое называется sys.dm_tran_current_transaction и возвращает информацию о текущей транзакции, выполняемой в текущем соединении. В окне запроса введите и выполните следующую инструкцию SELECT, чтобы получить информацию о блокировках и зафиксировать транзакцию.
SELECT resource_type, resource_associated_entity_id,
request mode, request_status
FROM sys.dm_tran_locks dml INNER JOIN
sys.dm_tran_current_transaction dmt
ON dml.request_owner_id = dmt.transaction_id;
COMMIT TRAN
4. Pезультат этого запроса показывает, что в ключе, представляющем строку в кластеризованном индексе, существует разделяемая блокировка (request_mode= S), а в соответствующей странице и таблице Поставщики существует блокировка разделяемого намерения (request_mode = IS). Значение GRANT в столбце request_status означает, что запрашиваемые блокировки предоставлены транзакции.
5. Теперь посмотрим, что произойдет, если мы изменим предложение WHERE таким образом, чтобы запрос возвращал больше строк. Внесите в предложение WHERE следующие изменения и выполните всю транзакцию.
USE Ваша_База_Данных;
GO
BEGIN TRAN
SELECT Имя_Поставщика, Статус
FROM Поставщики WITH (HOLDLOCK)
WHERE Код_Поставщика< ‘S5’
6. Далее изучим блокировки, выполнив следующий код:
SELECT resource_type, resource_associated_entity_id, request_mode,request_status
FROM sys.dm_tran_locks dml INNER JOIN
sys.dm_trancurrent_transaction dmt
ON dml.request_owner_id = dmt.transaction_id;
COMMIT TRAN
Мы видим, что разделяемая блокировка определена для объектного типа ресурсов, в этом случае, для таблицы Поставщики. SQL Server определяет, что для этой транзакции удержание блокировки на уровне таблицы будет проще и быстрее, чем удержание 7000 блокировок ключей со всеми зависимыми блокировками намерений. Поскольку SQL Server использовал уровень блокировки ТАБЛИЦА, ему не придется использовать блокировки намерений, ведь блокировка таблицы - самый верхний уровень в иерархии блокировок для данных. Чтобы узнать, какой объект блокируется, можно использовать функцию OBJECT_NAME. OBJECT_NAME в качестве аргумента принимает идентификатор объекта и возвращает имя объекта. (Столбец resource_associated_entity_id содержит идентификатор блокируемого объекта Object ID, если OBJECT представляет собой resource_type.)
7. Чтобы увидеть, как SQL Server блокирует данные в процессе изменения, введите и выполните следующую транзакцию для обновления (UPDATE) данных в таблице Поставщики и запросите связанные блокировки. В завершение выполняется инструкция ROLLBACK TRAN для отмены этих изменений.
USE Ваша_База_Данных;
GO
BEGIN TRAN
UPDATE Поставщики
SET Статус =35
WHERE Код_Поставщика =‘S5’;
SELECT resource_type, resource_associated_entity_id. request_mode. request_status
FROM sys.dm_tran_locks dml INNER JOlN
sys.dm_tran_current_transaction dmt
ON dml.request_owner_id = dmt.transaction_id;
ROLLBACK TRAN
Можно увидеть, что SQL Server блокирует ключ при помощи монопольной блокировки (request__mode = X). При любом изменении данных SQL Server выполняет монопольную блокировку и удерживает ее до тех пор, пока не завершится транзакция. Как уже говорилось ранее, SQL Server также использует блокировки изменений на первом этапе выполнения инструкций UPDATE. Поскольку мы запросили информацию о блокировках после инструкции UPDATE, блокировка строки уже была повышена до монопольной блокировки. Для страницы и таблицы снова существуют две блокировки монопольного намерения (request_mode = IX); кроме того, существует также блокировка под названием Sch-S для типа ресурсов METADATA. Блокировка Sch-S - это блокировка схемы, которая используется для того, чтобы запретить изменение схемы таблицы другими транзакциями в процессе обновления данных, потому что такие изменения не разрешаются в процессе изменения данных.
