Блокировка строки
Блокировка строки
В MGA наличие ожидающих завершения новых версий строки имеет следствием блокировку строки. При большинстве условий наличие новой подтвержденной версии блокирует запрос на изменение или удаление этой строки - это конфликт блокировки.
При получении запроса на изменение или удаление сервер проверяет состояние каждой транзакции, которая "владеет" новыми версиями строки. Если самая новая из этих владеющих транзакций является активной или была подтверждена, сервер отвечает запрашивающей транзакции в соответствии с ее контекстом (уровень изоляции и параметры разрешения блокировки).
Если транзакция самой новой версии является активной, запрашивающая транзакция по умолчанию будет ожидать ее завершения (подтверждения или отката), а затем сервер позволит ей продолжить свое выполнение. При этом если было задано NOWAIT, сервер вернет исключение конфликта запрашивающей транзакции.
Если транзакция самой новой версии подтверждена и запрашивающая транзакция имеет уровень изоляции SNAPSHOT (т. е. параллельный), сервер отвергает запрос и сообщает о конфликте блокировки. Если транзакция имеет уровень изоляции READ COMMITTED с установленным по умолчанию значением RECORD_VERSION, сервер выполняет запрос и записывает новую версию записи с идентификатором этой транзакции.
! ! !
ПРИМЕЧАНИЕ. Возможны другие условия, когда запрашивающая транзакция имеет уровень изоляции READ COMMITTED. На результат любого запроса транзакции могут также воздействовать необычные условия в контексте транзакции, которая владеет ожидающими завершения изменениями. Более подробную информацию об этих вариантах см. в главе 26, где детально рассматриваются параметры транзакции.
. ! .
Firebird не использует традиционную двухфазную блокировку для большинства обычных контекстов транзакции. Следовательно, все нормальные блокировки выполняются на уровне строки (такая блокировка называется оптимистической) - каждая строка доступна всем транзакциям чтения/записи, за исключением транзакции, выполняющей создание новой версии этой строки.
Во время успешного подтверждения старая версия записи становится устаревшей записью.
* Если выполнялась операция изменения, то новый образ становится самой последней подтвержденной версией. Оригинальный образ этой записи с идентификатором последней изменяющей транзакции становится доступным для сборки мусора.
* Если выполнялась операция удаления, то "остаток записи" заменяет устаревшую запись. Чистка или резервное копирование очищает этот остаток и освобождает физическое место на диске, занимаемое удаленной записью.
Сведения о чистке и сборке мусора см. в разд. "Гигиена базы данных" главы 15. Руководство по чистке находится в главе 39.
В итоге при нормальных условиях:
* любая транзакция может читать любую строку, которая была подтверждена до старта этой транзакции;
* любая транзакция чтения/записи может запрашивать изменение или удаление строки;
* пересылка (post) обычно будет успешной, если никакая другая транзакция чтения/записи не пересылала и не подтверждала изменения для новой версии этой записи. Транзакциям READ COMMITTED разрешается пересылать изменения, перезаписывающие подтвержденные версии более новых транзакций;
* если пересылка успешна, транзакция устанавливает "замок" на эту запись. Другие транзакции могут читать последнюю подтвержденную версию, однако ни одна пересылка изменения или удаления этой строки не будет успешной.