Минимизация взаимоблокировок

Хотя полностью избежать взаимоблокировок нельзя, следующие соглашения по написанию кода могут уменьшить вероятность возникновения взаимоблокировок. Минимизация взаимоблокировок приводит к увеличению пропускной способности системы (выполнению большего количества транзакций за единицу времени) и уменьшению накладных расходов системы на обслуживание, так как транзакции реже:

  • Откатываются с отменой всей выполненной транзакцией работы.

  • Повторно выполняются приложениями, так как при возникновении взаимоблокировок они откатывались.

Для минимизации взаимоблокировок:

  • Осуществляйте доступ к объектам в одинаковом порядке.

  • Избегайте взаимодействия с пользователем в транзакциях.

  • Уменьшайте размер транзакций, желательно помещая их в один пакет.

  • Используйте низкий уровень изоляции.

  • Используйте уровень изоляции строк, основанный на управлении версиями строк.

    • Установите параметр базы данных READ_COMMITTED_SNAPSHOT в ON для разрешения использования управления версиями строк транзакциями с уровнем изоляции READ COMMITTED.

    • Используйте изоляцию моментальных снимков.

  • Используйте связанные соединения.

Осуществление доступа к объектам в одинаковом порядке

Если все одновременные транзакции будут осуществлять доступ к объектам в одинаковом порядке, то появление взаимоблокировок менее вероятно. Например, если две одновременные транзакции блокируют таблицу Supplier, а затем таблицу Part, то одна транзакция блокируется в таблице Supplier до окончания выполнения другой транзакции. После фиксации или отката первой транзакции вторая продолжает работу, и взаимоблокировки не происходит. Использование хранимых процедур для всех изменений данных может стандартизировать порядок доступа к объектам.

Диаграмма, иллюстрирующая предотвращение взаимоблокировки

Отказ от взаимодействия с пользователем в транзакциях

Скорость выполнения пакетов без вмешательства пользователя гораздо выше, чем скорость выполнения пакетов, в которых пользователь должен вручную реагировать на запросы,поэтому нет необходимости создавать транзакции, в которых происходит взаимодействие с пользователем, например вводить запрашиваемый приложением параметр. Например, если транзакция ожидает ввода информации пользователем, а пользователь ушел на обед или отправился домой в конце рабочей недели, выполнение транзакции может завершиться только после его возвращения. Это уменьшает пропускную способность системы, так как любые блокировки, устанавливаемые транзакцией, будут сняты только после подтверждения или отката транзакции. Даже если взаимоблокировка не возникла, другие транзакции, требующие доступа к тем же ресурсам, окажутся заблокированными до окончания выполнения текущей транзакции.

Уменьшение размера транзакций и помещение их в один пакет

Обычно взаимоблокировка возникает, когда несколько долго выполняемых транзакций запускаются одновременно в одной базе данных. Чем длиннее транзакция, тем дольше будут удерживаться полученные монопольные блокировки или блокировки обновления, которые блокируют другие действия и могут привести к взаимоблокировке.

Помещение транзакций в один пакет сокращает объемы передачи данных по сети во время транзакции, уменьшая возможные задержки при завершении транзакций и снятии блокировок.

Использование низкого уровня изоляции

Определите, может ли транзакция выполняться при более низком уровне изоляции. Применение фиксации чтением позволяет транзакции считывать данные, считанные до этого (но не измененные) другой транзакцией, не ожидая завершения выполнения этой другой транзакции. Использование более низкого уровня изоляции, например фиксации чтением, устанавливает совмещаемые блокировки на более короткий промежуток времени, чем при использовании более высокого уровня изоляции, например сериализации. Это уменьшает количество конфликтов блокировок.

Использование уровня изоляции строк, основанного на управлении версиями строк

Если параметр базы данных READ_COMMITTED_SNAPSHOT установлен в ON, то транзакция, запущенная с уровнем изоляции подтверждения чтением, использует во время операция считывания управление версиями, а не совмещаемые блокировки.

ПримечаниеПримечание

Некоторые приложения зависят от блокировок и монополизации ресурсов, обеспечиваемых уровнем изоляции read committed. В такие приложения перед включением данного параметра необходимо внести изменения.

В изоляции моментальных снимков также применяется управление версиями строк, не использующее во время операций считывания разделяемых блокировок. Перед запуском транзакций с изоляцией моментальных снимков параметр ALLOW_SNAPSHOT_ISOLATION должен быть установлен в ON.

Применение этих уровней изоляции приводит к минимизации взаимоблокировок, возникающих между операциями считывания и записи.

Использование связанных соединений

При использовании связанных соединений два или более соединения, открытые одним и тем же приложением, могут действовать совместно друг с другом. Любые блокировки, используемые вторичными соединениями, устанавливаются так, как если бы они запрашивались первичным соединением, и наоборот. Поэтому соединения не блокируют друг друга.