Spec-Zone .ru
спецификации, руководства, описания, API
|
Этот раздел основывается на концептуальной информации о мертвых блокировках в Разделе 14.2.3.9, "Обнаружение мертвой блокировки и Откат". Это объясняет, как организовать операции базы данных, чтобы минимизировать мертвые блокировки и последующую обработку ошибок, требуемую в приложениях.
Мертвые блокировки являются классической проблемой в транзакционных базах данных, но они не опасны, если они не являются настолько частыми, что невозможно выполнить определенные транзакции вообще. Обычно, следует записать свои приложения так, чтобы они были всегда подготовлены переиздать транзакцию, если она откатывается из-за мертвой блокировки.
InnoDB
использует автоматическую блокировку на уровне строки. Можно получить мертвые
блокировки даже в случае транзакций, которые только вставляют или удаляют единственную строку. Это - то, потому
что эти операции не являются "действительно атомарными";
они автоматически устанавливают, соединяется (возможно, несколько) индексируют записи строки, вставленной или
удаленной.
Можно справиться с мертвыми блокировками и уменьшить вероятность их возникновения со следующими методами:
В любое время выйдите SHOW ENGINE INNODB STATUS
команда, чтобы определить причину последней
мертвой блокировки. Это может помочь Вам настроить свое приложение, чтобы избежать мертвых блокировок.
Если частое беспокойство причины предупреждений мертвой блокировки, соберите более
обширную отладочную информацию, перезапуская сервер с innodb_print_all_deadlocks
параметр конфигурации включается.
Информация о каждой мертвой блокировке, не только последний, записывается в журнале
ошибок MySQL. Удалите эту опцию и перезапустите сервер снова, как только отладка заканчивается.
Всегда готовьтесь переиздать транзакцию, если она перестала работать из-за мертвой блокировки. Мертвые блокировки не опасны. Только попробуйте еще раз.
Фиксируйте свои транзакции сразу после создания ряда связанных изменений. Маленькие транзакции являются менее склонными к коллизии. В частности не оставляйте интерактивный mysql сеанс открытым в течение долгого времени с незафиксированной транзакцией.
Если Вы используете чтения блокировки (SELECT ... FOR UPDATE
или SELECT ... LOCK IN SHARE
MODE
), попытайтесь использовать более низкий уровень изоляции такой как READ COMMITTED
.
Когда изменение многократных таблиц в пределах транзакции, или различных наборов
строк в той же самой таблице, делает те операции в непротиворечивом порядке каждый раз. Затем транзакции
формируют четко определенные очереди и делают не мертвую блокировку. Например, организуйте операции базы
данных в функции в пределах Вашего приложения, или вызовите сохраненные подпрограммы, вместо того, чтобы
кодировать многократные подобные последовательности INSERT
, UPDATE
, и DELETE
операторы в различных
местах.
Добавьте хорошо подобранный, индексирует к Вашим таблицам. Затем Ваши запросы
должны отсканировать, меньше индексируют записи и следовательно устанавливают меньше блокировок.
Использовать EXPLAIN SELECT
определить, который индексирует отношения сервера
MySQL как самое подходящее для Ваших запросов.
Использование меньше блокировки. Если можно позволить себе разрешить a SELECT
чтобы возвратить данные из старого снимка, не добавляйте пункт FOR UPDATE
или LOCK IN SHARE MODE
к этому. Используя READ COMMITTED
уровень изоляции хорош здесь, потому что каждое
непротиворечивое чтение в пределах той же самой транзакции читает из ее собственного нового снимка.
Если ничто иное не помогает, сериализируйте свои транзакции с блокировками на
уровне таблицы. Корректный способ использовать LOCK TABLES
с транзакционными таблицами, такой как InnoDB
таблицы, должен начать транзакцию с SET
autocommit = 0
(нет START TRANSACTION
) сопровождаемый LOCK TABLES
, и не вызывать UNLOCK TABLES
пока Вы не фиксируете транзакцию явно. Например, если
Вы должны записать в таблицу t1
и читайте из таблицы t2
,
можно сделать это:
SET autocommit=0;LOCK TABLES t1 WRITE, t2 READ, ...;...
do something with tables t1 and t2 here ...
COMMIT;UNLOCK TABLES;
Блокировки на уровне таблицы предотвращают параллельные обновления к таблице, избегая мертвых блокировок за счет меньшего количества скорости отклика для занятой системы.
Другой способ сериализировать транзакции состоит в том, чтобы составить
вспомогательную "семафорную" таблицу,
которая содержит только единственную строку. Имейте каждое обновление транзакции та строка прежде, чем
получить доступ к другим таблицам. Таким образом все транзакции происходят последовательным способом.
Отметьте что InnoDB
мгновенный алгоритм обнаружения мертвой блокировки
также работает в этом случае, потому что блокировка сериализации является блокировкой на уровне строки.
С MySQL блокировки на уровне таблицы метод тайм-аута должен использоваться, чтобы разрешить мертвые
блокировки.