В SQL Server существует отдельный поток, который периодически (по умолчанию 5 секунд, меньший интервал, если только что обнаружена взаимоблокировка) проверяет список ожиданий любых циклов. Т.е. он идентифицирует ресурс, который ожидает поток, затем он находит владельца этого ресурса и рекурсивно находит, какой ресурс этот поток в свою очередь ожидает, тем самым идентифицируя потоки, которые ждут ресурсы друг друга.
Если обнаружен тупик, то жертва выбирается для убийства с использованием этого алгоритма:
- Определите потоки, которые не подлежат уничтожению (например, поток, который откатывает транзакцию, не подлежит уничтожению).
- Найдите тему с наименьшим приоритетом взаимоблокировки.
- Выберите тот, который дешевле всего откатиться, то есть тот, который проделал наименьшую работу до сих пор.
Вы можете найти более подробную информацию об обнаружении взаимоблокировки серверов SQL здесь:
http://msdn.microsoft.com/en-us/library/ms178104.aspx
Владелец транзакции / разработчик приложения несет ответственность за минимизацию рисков возникновения взаимоблокировок и выполнение что они должны:
- Сделайте транзакции максимально короткими. Например, не показывайте форму входа после запуска транзакции и ждите ввода пользователя, вместо этого соберите всю необходимую информацию и запустите транзакцию.
- Используйте минимально возможный уровень изоляции, например, не устанавливайте сериализуемость, когда вы просто хотите временно показать некоторые значения пользователю. Обратите внимание, что установка правильного уровня изоляции является наукой сама по себе и выходит за рамки этого ответа.
- Если вы стали жертвой тупика, то есть вы получили ошибку # 1205, то прозрачно перезапустите транзакцию для вашего пользователя. Поскольку другая конкурирующая транзакция теперь, как мы надеемся, получила ресурсы, которые она ждала и завершила, не похоже, что вы снова столкнетесь с тем же тупиком.