Базовые блокировки базы данных
Одна из классических причин, по которой мы имеем тупик базы данных, - это когда две транзакции вставляют и обновляют таблицы в другом порядке.
Например, транзакция A вставляет в таблицу A, а затем таблицу B.
И транзакция B вставлена в таблицу B, за которой следует A.
Такой сценарий всегда находится под угрозой блокировки базы данных (при условии, что вы не используете сериализуемый уровень изоляции).
Мои вопросы:
-
Какие шаблоны вы используете в своем дизайне, чтобы убедиться, что все транзакции вставляются и обновляются в том же порядке.
В книге, которую я читал, было предложено сортировать заявления по имени таблицы. Вы сделали что-то подобное или другое - что обеспечило бы соблюдение всех вложений и обновлений в одном порядке?
-
Как насчет удаления записей? Удалить нужно начинать с дочерних таблиц и обновлений, а вставки нужно начинать с родительских таблиц. Как вы гарантируете, что это не запустится в тупик?
Ответы
Ответ 1
- Все транзакции
вставка\обновление в том же порядке.
- Удаление; идентифицировать записи
удаляется вне транзакции и
затем попытайтесь удалить в
наименьшая возможная сделка, например.
поиск первичного ключа или аналогичного
определенных на этапе поиска.
- Небольшие транзакции в целом.
- Индексация и другие показатели
настройка для обеих скоростных транзакций
и содействовать поиску индекса
tablescans.
- Избегайте "Горячих столов",
например одна таблица с приращением
счетчики для других таблиц
ключи. Любой другой тип коммутатора
конфигурация является рискованной.
- Особенно если не использовать Oracle, узнайте
смотрящее поведение целевой
СУРБД подробно (оптимистично/
пессимистический, уровень изоляции и т.д.)
Убедитесь, что вы не допускаете блокировки строк
эскалировать в столовые замки, как некоторые
RDMSes будет.
Ответ 2
Тупики не большие. Просто будьте готовы повторить транзакции при неудаче.
И держите их короткими. Короткие транзакции, состоящие из запросов, которые касаются очень немногих записей (посредством магии индексирования), идеально подходят для минимизации взаимоблокировок - меньше строк блокируются и на более короткий период времени.
Вам нужно знать, что современные механизмы баз данных не блокируют таблицы; они фиксируют строки; поэтому взаимоблокировки немного менее вероятны.
Вы также можете избежать блокировки с помощью MVCC и уровня изоляции транзакции CONSISTENT READ: вместо блокировки некоторые потоки будут видеть только устаревшие данные.
Ответ 3
-
Осторожно разрабатывайте процессы базы данных, чтобы устранить как можно больше транзакций, связанных с несколькими таблицами. Когда у меня был контроль за базой данных, никогда не было случая тупика, для которого я не мог разработать условие, вызвавшее его. Это не значит, что они не существуют и, возможно, изобилуют ситуациями за пределами моего ограниченного опыта; но у меня не было недостатка в возможности улучшить дизайн, вызывающий такие проблемы. Одна очевидная стратегия - начать с хронологической таблицы только для записи для вставки новых полных атомных транзакций без взаимозависимостей и применить их эффекты в упорядоченном асинхронном процессе.
-
Всегда используйте уровни изоляции базы данных по умолчанию и параметры блокировки, если вы не уверены, какие риски они понесут, и доказали это путем тестирования. Перепроектируйте свой процесс, если это вообще возможно. Затем наложите наименьшее увеличение защиты, требуемое для устранения риска (и теста, чтобы доказать это.) Не увеличивайте ограничиваемость "на всякий случай" - это часто приводит к непреднамеренным последствиям, иногда того типа, которого вы хотели избежать.
-
Чтобы повторить точку с другого направления, большинство из того, что вы будете читать на этом и других сайтах, выступающих за изменение настроек базы данных, чтобы справиться с рисками транзакций и проблемами с блокировкой, вводит в заблуждение и/или ложно, что продемонстрировано тем, как они постоянно конфликтуют друг с другом. К сожалению, особенно для SQL Server, я не нашел источника документации, который не является безнадежно запутанным и неадекватным.
Ответ 4
Я обнаружил, что одна из лучших инвестиций, которую я когда-либо делал в предотвращении взаимоблокировок, заключалась в использовании объектного реляционного сопоставителя, который мог бы заказывать обновления баз. Точный порядок не имеет значения, если каждая транзакция записывается в том же порядке (и удаляется точно в обратном порядке).
Причина, по которой это позволяет избежать большинства взаимоблокировок, заключается в том, что ваши операции всегда являются таблицей A, а затем таблицей B, а затем таблицей C (которая, возможно, зависит от таблицы B).
Вы можете достичь аналогичного результата, если вы выполняете осторожность в своих хранимых процедурах или коде доступа к уровню данных. Единственная проблема заключается в том, что она требует большой осторожности, чтобы сделать это вручную, тогда как ORM с концепцией Unit of Work может автоматизировать большинство случаев.
UPDATE: удаление должно выполняться вперёд, чтобы убедиться, что все вы ожидаете (вам все равно нужны номера версий или временные метки), а затем удалите их назад, как только все будет проверено. Поскольку это все должно произойти в одной транзакции, возможность чего-то, выходящего из-под вас, не должна существовать. Единственная причина, по которой ORM делает это в обратном направлении, - это подчиняться ключевым требованиям, но если вы сделаете чек вперёд, у вас появятся все блокировки, которые вам уже нужны.
Ответ 5
Я анализирую все действия базы данных, чтобы определить для каждого из них, если это должно быть в транзакции нескольких операторов, а затем для каждого такого случая, какой минимальный уровень изоляции необходим для предотвращения взаимоблокировок... Как вы сказали, сериализуемое обязательно сделают это...
Как правило, только очень немногие действия с базой данных требуют, в первую очередь, транзакции с несколькими операторами, и из них только некоторые требуют сериализации для устранения взаимоблокировок.
Для тех, кто это делает, установите уровень изоляции для этой транзакции, прежде чем вы начнете, и reset, независимо от вашего значения по умолчанию после его совершения.
Ответ 6
Ваш пример будет проблемой только в том случае, если база данных заблокировала таблицу ENTIRE. Если ваша база данных делает это... run:)