Блокировка базы данных - PullRequest
       7

Блокировка базы данных

18 голосов
/ 10 апреля 2009

Одна из классических причин, по которым мы имеем тупик в базе данных, - это когда две транзакции вставляют и обновляют таблицы в другом порядке.

Например, транзакция A вставляется в таблицу A, а затем в таблицу B.

И транзакция B вставляет в Таблицу B, за которой следует A.

Такой сценарий всегда подвергается риску тупика базы данных (при условии, что вы не используете сериализуемый уровень изоляции).

Мои вопросы:

  1. Какие шаблоны вы используете в своем проекте, чтобы убедиться, что все транзакции вставляются и обновляются в одном и том же порядке. Книга, которую я читал, была с предложением отсортировать утверждения по названию таблицы. Делали ли вы что-то подобное или другое - что обеспечило бы, чтобы все вставки и обновления были в одном и том же порядке?

  2. А как насчет удаления записей? Удаление должно начинаться с дочерних таблиц и обновлений, а вставки должны начинаться с родительских таблиц. Как вы гарантируете, что это не приведет к тупику?

Ответы [ 6 ]

13 голосов
/ 12 апреля 2009
  1. Все транзакции вставка \ обновление в том же порядке.
  2. Удаляет; определить записи, которые будут удален за пределы транзакции и затем попытайтесь удалить в наименьшая возможная транзакция, например поиск по первичному ключу или подобному идентифицировано на этапе поиска.
  3. Мелкие транзакции, как правило.
  4. Индексирование и другие показатели настройка на обе скорости транзакций и продвигать поиски индекса по tablescans.
  5. Избегайте «горячих столов», например одна таблица с приращением счетчики для других таблиц первичные ключи. Любой другой тип «распределительного щита» конфигурация рискованная.
  6. Особенно, если не используете Oracle, учитесь выглядящее поведение цели СУБД подробно (оптимистично / пессимистичный, уровень изоляции и т. д.) Убедитесь, что вы не разрешаете блокировку строк перерасти в блокировки таблицы, как некоторые RDMS будут.
7 голосов
/ 10 апреля 2009

тупики не важны. Просто будьте готовы повторить ваши транзакции в случае неудачи.

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

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

Вы также можете избежать блокировки, используя MVCC и уровень изоляции транзакции CONSISTENT READ: вместо блокировки некоторые потоки будут просто видеть устаревшие данные.

3 голосов
/ 12 апреля 2009
  1. Тщательно спроектируйте процессы базы данных, чтобы исключить как можно больше транзакций, которые включают несколько таблиц. Когда у меня был контроль над дизайном базы данных, никогда не было случая тупика, из-за которого я не мог спроектировать условие, которое его вызвало. Нельзя сказать, что они не существуют и, возможно, изобилуют ситуациями вне моего ограниченного опыта; но у меня не было недостатка в возможностях улучшить дизайн, вызывающий такие проблемы. Одна очевидная стратегия состоит в том, чтобы начать с хронологической таблицы только для записи для вставки новых завершенных атомарных транзакций без взаимозависимостей и применять их эффекты в упорядоченном асинхронном процессе.

  2. Всегда используйте уровни изоляции базы данных по умолчанию и настройки блокировки , если только вы абсолютно уверены в том, какие риски они несут, и доказали это путем тестирования. Перепроектируйте ваш процесс, если это вообще возможно, в первую очередь. Затем наложите наименьшее увеличение защиты, необходимое для устранения риска (и протестируйте, чтобы доказать это). Не увеличивайте ограничения «на всякий случай» - это часто приводит к непреднамеренным последствиям, иногда того типа, который вы намеревались избежать.

  3. Чтобы повторить точку зрения в другом направлении, большая часть того, что вы прочтете на этом и других сайтах, выступающих за изменение настроек базы данных, чтобы справиться с транзакционными рисками и проблемами блокировки, вводит в заблуждение и / или ложно, что демонстрируется тем, как они так часто конфликтуют друг с другом. К сожалению, особенно для SQL Server, я не нашел ни одного источника документации, который бы не был безнадежно запутанным и неадекватным.

2 голосов
/ 10 апреля 2009

Я обнаружил, что одним из лучших вложений, которые я когда-либо делал во избежание взаимоблокировок, было использование Object Relational Mapper, который мог бы заказывать обновления базы данных. Точный порядок не важен, если каждая транзакция записывает в одном и том же порядке (и удаляет точно в обратном порядке).

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

Вы можете достичь аналогичного результата, если будете проявлять осторожность в своих хранимых процедурах или в коде доступа уровня данных. Единственная проблема заключается в том, что для этого требуется большой осторожность, чтобы делать это вручную, тогда как ORM с концепцией Unit of Work может автоматизировать большинство случаев.

ОБНОВЛЕНИЕ: удаление должно быть запущено вперед, чтобы убедиться, что все версии, которые вы ожидаете (вам все еще нужны номера версий записей или временные метки), а затем удалить в обратном направлении, когда все подтвердит. Поскольку все это должно происходить в одной транзакции, вероятность того, что что-то изменится из-под вас, не должна существовать. Единственная причина, по которой ORM делает это задом наперед, состоит в том, чтобы соблюдать ключевые требования, но если вы выполните проверку вперед, у вас будут все замки, которые вам нужны, уже под рукой.

2 голосов
/ 10 апреля 2009

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

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

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

0 голосов
/ 10 апреля 2009

Ваш пример будет проблемой только в том случае, если база данных заблокирует ВСЮ таблицу. Если ваша база данных это делает ... запустите:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...