- •Практическая работа. Бизнес-транзакции и транзакции sql Server
- •Управление изоляцией транзакций
- •Мониторинг блокировок
- •Уровень изоляции транзакции
- •Используем только чтение зафиксированных данных
- •Применяем уровень изоляции read commited
- •Применяем уровень изоляции read commited snapshot
- •Как добиться согласованных повторяющихся операций чтения
- •Применяем уровень изоляции snapshot
- •Как предотвратить параллельные изменения данных
- •Применяем уровень изоляции repeatable read
- •Применяем уровень изоляции serializable
- •Борьба с блокированиями
- •Выполняем мониторинг блокирований при помощи динамических административных представлений
- •Борьба с взаимоблокировками
- •Разыгрываем простой сценарий взаимоблокировки
- •5. Закройте все окна запросов.
Борьба с взаимоблокировками
Взаимоблокировки представляют собой особые сценарии блокирования, которые приводят к бесконечной блокировке, если не разрешаются автоматически. Это может произойти, когда две или более транзакций блокируют друг друга. Если такая ситуация имеет место, то каждая транзакция ожидает снятия блокировок каждой другой транзакцией, но этого не происходит, потому что другие транзакции ожидают того же. Эта ситуация называется взаимоблокировкой, потому что транзакции никогда не разблокируются. Чтобы предотвратить такое развитие событий, SQL Server разрешает такие ситуации самостоятельно, выполняя откат для одной из транзакций и возвращая ошибку соединению, чтобы дать возможность другим транзакциям завершить работу.
Разыгрываем простой сценарий взаимоблокировки
Давайте воспроизведем простой сценарий взаимоблокировки, чтобы посмотреть, как SQL Server управляет взаимоблокировками.
Запустите SQL Server Management Studio и откройте окно New Query(Новый запрос).
Введите и выполните следующий код, чтобы создать небольшую таблицу и вставить в нее данные без закрытия транзакции.
USE tempdb;
CREATE TABLE t1 (i int)
BEGIN TRAN
INSERT INTO t1 Values(1)
3. Откройте еще одно окно запроса и выполните следующие инструкции, чтобы создать маленькую таблицу, вставить в нее данные и попытаться обновить таблицу tl из окна запроса Query Window 1. Транзакция будет блокирована, поскольку транзакция в окне запросаQuery Window 1 пока не зафиксирована.
USE tempdb;
CREATE TABLE t2(i int)
BEGIN TRAN
INSERT INTO t2 Values( 1)
UPDATE t1 SET i = 2
4. He завершайте этот запрос и перейдите в окно запроса Query Window1. Выполните следующую инструкцию UPDATE, чтобы обновить таблицу t2 и посмотрите, что произойдет.
UPDATE t2 SET i = 2
Через несколько секунд одна из транзакций отменяется, и возвращается сообщение об ошибке
Это произошло потому, что транзакции блокировали друг друга. Транзакция в окне запроса Query Window1 владеет блокировкой на таблицу t1 и пытается обновить таблицу t2, а транзакция в окне запросов Query Window2 владеет блокировкой на таблицу t2 и пытается обновить таблицу t1. Следовательно, обе транзакции будут бесконечно ожидать, пока оппонирующая транзакция снимет блокировку. Такие ситуации выявляются SQL Server и разрешаются путем отката одной из вовлеченных транзакций и выдачей ошибки 1205 соответствующему соединению.
5. Закройте все окна запросов.
Чтобы предотвратить взаимоблокировки или, хотя бы, бороться с ними, следует соблюдать несколько правил.
Соблюдайте правила минимизации блокирований. Если меньше блокирований, меньше и шансов для взаимоблокировки.
Всегда обращайтесь к объектам в пределах транзакций в одном и том же порядке. Если бы обе транзакции в рассмотренном выше примере обращались к таблицам в соответствии с одним порядком, то не было бы возможностей для взаимоблокировки. Следовательно, следует определить список доступа для всех таблиц в базе данных.
Проверяйте наличие ошибки 1205 в вашем обработчике ошибок и повторите передачу транзакции, когда такая ошибка обнаружится.
Добавьте в обработчик ошибок процедуру регистрации деталей ошибки.
Если вы будете следовать этим правилам, то у вас будут хорошие шансы избежать взаимоблокировок. Если они будут происходить, то это остается незаметным для пользователей, потому что транзакция автоматически перезапустится, но при этом вы сможете отслеживать взаимоблокировки через журналы.
