- •Практическая работа. Бизнес-транзакции и транзакции sql Server
- •Управление изоляцией транзакций
- •Мониторинг блокировок
- •Уровень изоляции транзакции
- •Используем только чтение зафиксированных данных
- •Применяем уровень изоляции read commited
- •Применяем уровень изоляции read commited snapshot
- •Как добиться согласованных повторяющихся операций чтения
- •Применяем уровень изоляции snapshot
- •Как предотвратить параллельные изменения данных
- •Применяем уровень изоляции repeatable read
- •Применяем уровень изоляции serializable
- •Борьба с блокированиями
- •Выполняем мониторинг блокирований при помощи динамических административных представлений
- •Борьба с взаимоблокировками
- •Разыгрываем простой сценарий взаимоблокировки
- •5. Закройте все окна запросов.
Используем только чтение зафиксированных данных
В SQL Server уровень изоляции READ COMMITED - это уровень изоляции по умолчанию при установлении нового соединения. Этот уровень существует в двух разновидностях: READ COMMITTED (чтение зафиксированных данных) и READ COMMITTED SNAPSHOT (чтение зафиксированных данных, мгновенный снимок). Применяемый тип определяется в параметрах базы данных. Уровень изоляции READ COMMITED ожидает снятия блокировок перед чтением данных, тогда как уровень изоляции READ COMMITTED SNAPSHOT использует управление версиями строк и читает последнюю версию зафиксированных данных, когда данные заблокированы другой транзакцией.
Применяем уровень изоляции read commited
Запустите SQL Server Management Studio и откройте окно New Query(Новый запрос).
Введите и выполните следующие инструкции, чтобы прочитать поля Имя_Поставщика и Статус в таблице Поставщики если Код_Поставщика = ‘S1’.
3. Далее представим, что другая транзакция изменяет столбец Статус, в то время как первая транзакция все еще открыта. Откройте еще одно окно запроса и выполните следующий пакет, чтобы обновить (UPDATE) столбец Статус для этого же поставщика без фиксации транзакции.
Инструкция UPDATE выполняется без каких-либо проблем. Она оказывает действие на одну строку данных, хотя сначала эти данные были считаны транзакцией из первого окна запроса, и эта транзакция еще не завершилась. Это происходит потому, что уровень изоляции READ COMMITED не удерживает разделяемые блокировки, которые используются инструкцией SELECT, до окончания транзакции. Блокировки снимаются сразу после того, как данные прочитаны SQL Server.Это может оказаться проблемой, если вам нужны согласованные операции считывания данных в процессе вашей транзакции. А сейчас вернемся к окну запроса 1 и снова попробуем выполнить чтение данных.
Запрос не завершается, поскольку инструкция SELECT заблокирована. SQL Server пытается получить разделяемую блокировку на ключ столбца Код_Поставщика=1, но это невозможно, ведь транзакция UPDATE в окне запроса Query Window 2 владеет монопольной блокировкой на этот ключ. Хотя окно запроса Query Windows 2 находится в режиме READ COMMITED (поскольку мы не изменяли уровень по умолчанию), монопольная блокировка все еще не снята. Эта блокировка существует потому, что монопольные блокировки для изменений данных всегда удерживаются до окончания транзакции.
6. Перейдите в окно запроса Query Window 2, не закрывая окно запросов Query Window 1. Введите и выполните следующую инструкцию SELECT, чтобы получить информацию о предоставленных и ожидающих блокировках в базе данных.
SELECT resource_еype, resource_associated_entity_id,
request_mode, request_status
FROM sys.dm_tran_locks
Мы видим, что одна из разделяемых блокировок имеет статус WAIT. Это запрос, выполняемый в окне Query Window 1. Он ожидает завершения запроса в окне Query Window 2, который владеет монопольной блокировкой, предоставленной на тот же ресурс.
Выполните инструкцию ROLLBACK TRAN в окне запроса QueryWindow 2, чтобы отменить инструкцию UPDATE, и перейдите в окно Query Window 1. Вы видите, что запрос в этом окне запроса завершился, и его результат не отличается от полученного до этого. Когда транзакция в окне запроса Query Window 2 завершилась, блокировки были сняты, и запрос в окне Query Window 1 больше не был блокирован. Поскольку транзакция в окне Query Window 2 подверглась откату, мы получили в результате в окне запроса Query Window 1 исходные данные. Если бы транзакция в окне запроса Query Window2 была зафиксирована, то в результате в окне запроса Query Window1 мы получили бы новые данные.
Выполните инструкцию COMMIT TRAN в окне запроса QueryWindow 1, после чего закройте все окна запросов.
В этом примере мы увидели, что в режиме уровня изоляции READ COMMITED SQL Server ждет снятия монопольных блокировок, чтобы возвратить только актуальные и зафиксированные данные. Кроме того, нам стало ясно, что разделяемые блокировки удерживаются только на время чтения данных, а вот монопольные блокировки всегда удерживаются до фиксации транзакции. Такое поведение может вызвать проблемы, когда множество транзакций изменяют данные почти все время. В такой ситуации чтение данных может быть очень медленным из-за монопольных блокировок. Но в некоторых ситуациях может оказаться подходящим использование последней зафиксированной версии данных. В таких ситуациях можно изменить уровень изоляции READ COMMITTED на уровень изоляции READ COMMITTED SNAPSHOT.
