Конфликты блокировки
Конфликты блокировки
Конфликт блокировки появляется, когда конкурирующие транзакции пытаются изменить или удалить одну и ту же строку в то время, когда вид состояния базы данных для этих транзакций частично перекрывается. Конфликты блокировок являются запланированным результатом уровней изоляции транзакций в Firebird и стратегии поддержания многих версий записи, защищая изменяемые данные от неконтролируемой перезаписи параллельными операциями над одними и теми же данными.
Эта стратегия работает хорошо только в случае двух условий, которые приводят к конфликтам блокировки.
* Условие 1: одна транзакция (наша транзакция) отправила на сервер изменение или удаление строки. В это время другая транзакция, стартовавшая до того, как наша транзакция заблокировала эту строку, пытается ее изменить или удалить. Другая транзакция получает конфликт блокировки и имеет два варианта выбора:
• она может отменить свою попытку и позже снова повторить ее для вновь подтвержденной версии строки;
• она может ждать, пока наша транзакция либо подтвердит, либо отменит свою работу.
* Условие 2: наша транзакция блокирует для записи целую таблицу, если имеет уровень изоляции для таблицы SNAPSHOT TABLE STABILITY или использует резервирование таблицы с помощью PROTECTED, а другая транзакция пытается изменить или удалить строку или добавить новую строку.
Предположим, что наша транзакция посылает изменение строки. Появляется другая транзакция и запрашивает изменение или удаление той же строки. При уровне изоляции SNAPSHOT и режиме WAIT другая транзакция будет ожидать, пока наша транзакция завершит свою работу путем подтверждения или отката.
Если наша транзакция подтверждает изменения, то другая транзакция получит отказ по конфликту изменения. Клиент, который запустил другую транзакцию, должен иметь обработчик исключений, который либо откатит транзакцию и заново ее запустит для повторной выдачи запроса, либо просто подтвердит транзакцию и завершит работу.
Вызов COMMIT в обработчике исключения конфликта блокировки не рекомендуется, поскольку он разрушает атомарность транзакции - некоторая работа будет завершена, некоторая нет, и впоследствии будет невозможно предсказать состояние базы данных[97].
К сожалению, Firebird имеет тенденцию объединять все исключения блокировки и сообщает о них как "deadlock" (взаимная блокировка). Нормальные случаи, которые были описаны, не являются взаимной блокировкой.