SELECT не могут взаимоблокироваться с другими SELECT, потому что они получают только общие блокировки. Вы говорите, что мы должны учитывать, что эти SELECT теперь «требуют монопольных блокировок чтения», но мы не можем это учитывать, потому что 1) нет такой вещи, как exlusive read lock
и 2) чтения не получают эксклюзивные блокировки.
Но вы задаете более общий вопрос, могут ли простые утверждения зайти в тупик. Ответ однозначен, звучит ДА . Блокировки обнаруживаются при исполнении, не анализируются заранее и сортируются, а затем приобретаются в некотором порядке. Для движка было бы невозможно заранее узнать необходимые блокировки, потому что они зависят от фактических данных на диске, и прочитать данные, которые нужны двигателю для ... блокировки данных.
Взаимные блокировки между простыми утверждениями (SELECt против UPDATE или SELECT против DELETE) из-за разного порядка доступа к индексу довольно распространены и их очень легко исследовать, диагностировать и исправлять. Но обратите внимание, что всегда включает операцию записи, так как чтение не может блокировать друг друга. Для этого обсуждения добавление подсказки UPDLOCK или XLOCK к SELECT следует рассматривать как запись. Вам даже не нужно JOIN, вторичный индекс может привести к проблеме порядка доступа, приводящей к взаимоблокировке, см. Чтение / запись тупика .
И, наконец, написание SELECT FROM A JOIN B
или написание SELECT FROM B JOIN A
совершенно не имеет значения. Оптимизатор запросов может свободно изменять порядок доступа по своему усмотрению, фактический текст запроса никак не влияет на порядок выполнения.
Обновлено
Как тогда мы можем построить общее
стратегия к ЧИТАТЬ
база данных "несколько лиц", которая
не тупик?
Боюсь, рецепт печенья не существует. Решение будет зависеть от случая к случаю. В конечном счете, в приложениях для баз данных тупики становятся реальностью. Я понимаю, что это может звучать абсурдно, как в «мы приземлились на Луну, но мы не можем написать правильное приложение для базы данных», но существуют сильные факторы, которые в значительной степени гарантируют, что приложения в конечном итоге столкнутся с тупиками. Счастливые блокировки - - - проще всего справиться с ошибками, просто прочитайте снова состояние, примените логику, переписайте новое состояние. Теперь, как говорится, есть некоторые хорошие практики, которые могут значительно снизить частоту взаимоблокировок вплоть до того момента, когда они почти исчезли:
- Попробуйте иметь согласованный шаблон доступа для Пишет . Имеют четко определенные правила, в которых говорится, что «транзакция всегда должна иметь таблицы в следующем порядке:
Customers
-> OrderHeaders
-> OrderLines
.» Обратите внимание, что заказ должен выполняться внутри транзакции . По сути, ранжируйте все таблицы в вашей схеме и укажите, что все обновления должны происходить в порядке ранжирования. Это в конечном итоге сводится к дисциплине кода отдельного участника, пишущего код, так как он должен гарантировать, что он пишет, что обновление выполняется в правильном порядке внутри транзакции.
- Уменьшите длительность записи. Обычная мудрость заключается в следующем: в начале транзакции выполните все чтения (прочитайте существующее состояние), затем обработайте логику и вычислите новые значения, затем запишите все обновления в конце транзакции. Избегайте паттернов типа «read-> write-> logic-> read-> write», вместо этого делайте «read-> read-> logic-> write-> write». Конечно, истинное мастерство заключается в том, как справляться с реальными, реальными, индивидуальными случаями, когда очевидно, что один должен сделать запись в середине транзакции. Особо следует сказать о конкретном типе транзакции: транзакции, управляемые очередью, которые по определению начинают свою деятельность путем снятия с очереди (= запись) из очереди. Эти приложения всегда были чрезвычайно трудными для написания и подвержены ошибкам (особенно тупикам), к счастью, есть способы сделать это, см. Использование таблиц в качестве очередей .
- Уменьшите количество чтений. Сканирование таблиц является самой распространенной причиной тупиковых ситуаций. Правильная индексация не только устранит взаимоблокировки, но также может повысить производительность в процессе.
- Снимок изоляции . Это самая близкая вещь, которую вы получите на бесплатный обед, чтобы избежать тупиков. Я намеренно поставил его последним, потому что он может маскировать другие проблемы (например, неправильное индексирование) вместо того, чтобы их исправлять.
Попытка решить эту проблему с помощью LockCustomerByXXX
подхода, боюсь, не работает. Пессимистическая блокировка не масштабируется. Оптимистичный параллелизм обновления - это путь, если вы хотите добиться какой-либо достойной производительности.