Режим блокировки определяет, как будут разрешаться конфликты. Если возникает конфликт, то у транзакции, обнаружившей конфликт, есть два выхода - либо немедленно возбудить исключение, либо подождать некоторое время, после чего опять попытаться разрешить конфликт.
Соответственно есть два варианта режима блокировки - wait и nowait. По умолчанию используется режим wait.
Конфликты, о которых идет речь, возникают как в случае чтения записей, так и в случае записи. На конфликты при чтении записей, помимо wait/nowait, влияют также установки уровня изоляции, и поэтому мы их рассмотрим в разделе про уровни изоляции. А вот на объяснение влияния режима блокировки на конфликты при записи уровень изоляции не влияет, поэтому мы сейчас рассмотрим его.
* Рассмотрим случай, когда транзакция А
* если транзакция Б запущена в режиме wait, то она будет ожидать завершения транзакции А, и если А завершится подтверждением (commit), то вставленная в Б запись будет признана неактуальной и возникнет ошибка Deadlock, а если она откатится (rollback), то изменения в транзакции Б будут приняты и она сможет подтвердить их (т. е. сделать commit);
* если транзакция Б запущена в nowait, то немедленно возникнет ошибка 'lock conflict on no wait transaction'.
* Рассмотрим другой случай: транзакция А
* если Б в режиме wait, то она будет ждать пока А не подтвердится или не отменится; если А подтвердится, то в Б возникнет ошибка 'Deadlock - update conflict with concurrent update', - потому как А подтвердила свои изменения, изменения в Б признаются неактуальными; если же транзакция А откатится, Б получит возможность подтвердиться;
* если Б в режиме nowait, то немедленно возникнет ошибка 'lock conflict on no wait transaction'.
Возможно, неясна практическая ценность описаний режима блокировки. Однако чуть ниже это поможет понять суть рекомендованных наборов параметров для транзакций в типичных приложениях баз данных.
Вы, вероятно, заметили, что в сообщении об ошибке конфликта блокировки фигурирует слово "deadlock", однако это слово выбрано не совсем удачно. В переводе с английского оно означает "мертвая блокировка", или "взаимоблокировка". В нашем случае, несмотря на грозное сообщение, никаких взаимоблокировок не возникает.
Что же такое взаимоблокировка на самом деле и когда она может возникнуть?
Взаимоблокировка - классическая проблема при синхронизации доступа к ресурсу, при котором принципиально невозможна дальнейшая работа конкурирующих транзакций. Для иллюстрации рассмотрим две транзакции Т1 и Т2
и два ресурса - А и В; в контексте разговора о базах данных ресурсами могут быть, например, записи в некоторой таблице. Допустим, выполняется такая последовательность действий:
* Транзакция Т1 блокирует ресурс А, после чего благополучно работает с ним.
* Транзакция Т2 блокирует ресурс В, после чего также с ним работает.
* Транзакция Т1 желает поработать с ресурсом В, для чего она пытается установить на него блокировку. Так как в это время ресурс В уже занят транзакцией В, транзакция Т1 входит в состояние ожидания.
* Транзакция Т2 желает поработать с ресурсом А, пытается выполнить его блокирование и также переходит в состояние ожидания.
В результате мы имеем печальную ситуацию: транзакции не имеют никакого шанса продолжить свое выполнение из-за того, что намертво блокируют друг друга. Любой сервер баз данных должен быть способен выходить из этой ситуации по возможности достойно, и InterBase не исключение. Проблема решается выбором одной из транзакций в качестве жертвы и ее откате, при этом другая транзакция получает возможность выполниться до конца.
Алгоритм распознавания ситуации взаимоблокировки в InterBase не запускается сразу при возникновении конфликта, что сделано из соображений производительности. Вместо этого выдерживается определенный интервал времени, задаваемый параметром DEADLOCK_TIMEOUT в конфигурационном файле InterBase ibconfig, только после этого и производится сканирование таблицы блокировок на предмет взаимного блокирования.
В реальной практике программирования баз данных взаимоблокировки возникают крайне редко, поэтому не стоит считать, что вам так повезло, увидев слово "deadlock" в сообщении об ошибке. Скорее всего это всего лишь конфликт обновления.
Теперь давайте рассмотрим параметры, которые влияют на уровни изоляции.
Итак, как было упомянуто выше, уровень изоляции транзакции определяет, какие изменения, сделанные в других транзакциях, может видеть данная транзакция.