Резервирование таблиц
Резервирование таблиц
Firebird поддерживает режим блокировки таблиц для обеспечения полной блокировки одной или более таблиц в процессе выполнения транзакции. Необязательное предложение RESERVING <список таблиц> запрашивает немедленную полную блокировку всех подтвержденных строк указанных таблиц, предоставляя транзакции исключительный доступ за счет любых транзакций, конкурирующих с этой транзакцией.
В отличие от обычной тактики блокирования резервирование блокирует все строки пессимистически - оно действует с момента запуска транзакции, а не ожидает момента, когда потребуется блокировка индивидуальной строки.
Резервирование таблиц имеет три основные цели.
* Обеспечение блокировки таблиц на момент начала транзакции, а не в то время, когда к ним обращается первый оператор, что происходит в случае изоляции TABLE STABILITY, используемом для блокировки на уровне таблиц. Режим разрешения блокировки (WAIT/NOWAIT) применяется во время запроса транзакции, когда возникает конфликт с другими транзакциями, имеющими изменения данных, ожидающих завершения. В этом случае результатом будет обработка запроса при WAIT и отказ в обработке при NOWAIT. Такая возможность резервирования таблиц важна, потому что резко сокращает вероятность взаимных блокировок.
* Обеспечение зависимой блокировки (т. е. блокировки таблиц, к которым могут происходить обращения в триггерах и в ограничениях целостности). Зависимая блокировка не является нормальной в Firebird. При этом она устраняет конфликты изменения, появляющиеся при конфликтах непрямых зависимостей.
* Увеличение приоритета транзакции в отношении одной или более таблиц, с которыми она будет работать. Например, транзакция SNAPSHOT, которой нужен исключительный доступ по записи ко всем строкам какой-либо таблицы, может ее зарезервировать, оставляя обычным приоритет по отношению к строкам других таблиц. Это менее агрессивный способ применения блокировки на уровне таблицы, чем альтернативный, использующий уровень изоляции TABLE STABILITY.
В транзакции вы можете резервировать более одной таблицы.
Использование резервирования таблиц
Использование резервирования таблиц с уровнями изоляции SNAPSHOT и READ COMMITTED является более предпочтительным, чем с SNAPSHOT TABLE STABILITY, когда требуется блокировка на уровне таблицы. Резервирование таблиц является менее агрессивным и более гибким способом предварительной блокировки таблиц. Он доступен для использования с любым уровнем изоляции. При этом его использование с SNAPSHOT TABLE STABILITY не рекомендуется, поскольку он не имеет эффекта при ограничениях доступа к таблицам, к которым транзакции может понадобиться доступ и которые находятся за пределами предложения RESERVING.
Преимущественная блокировка таблиц не является средством для ежедневного использования, но она может быть полезной в таких задачах, как предварительная оценка отчетности или получение отчета по "замороженным запасам" перед инвентаризацией.
Параметры резервирования таблиц
Каждое резервирование таблиц может быть сконфигурировано с помощью различных атрибутов для задания того, как должны трактоваться разные транзакции при запросах доступа к зарезервированным таблицам.
! ! !
ПРИМЕЧАНИЕ. Транзакция SNAPSHOT TABLE STABILITY не может получить доступ ни к какой таблице, зарезервированной с помощью средства резервирования таблиц.
. ! .
Вариантами выбора являются:
[PROTECTED | SHARED] {READ | WRITE}
Атрибут PROTECTED предоставляет транзакции исключительный доступ к таблице по чтению и позволяет другим транзакциям с уровнями изоляции SNAPSHOT и READ COMMITTED читать строки. Запись ограничивается одним или двумя модификаторами:
* PROTECTED WRITE позволяет текущей транзакции писать в таблицу и блокирует запись другими транзакциями;
* PROTECTED READ запрещает запись в таблицу для любой транзакции, включая текущую.
Атрибут SHARED позволяет любой транзакции SNAPSHOT или READ COMMITTED читать из таблицы и предоставляет два режима для параллельных изменений другими транзакциями:
* SHARED WRITE любой транзакции чтения/записи SNAPSHOT или транзакции чтения/записи READ COMMITTED изменять строки в наборе, пока никакая транзакция не имеет или не запросит исключительного доступа по записи;
* SHARED READ является наиболее либеральным условием резервирования. Этот режим позволяет любой другой транзакции чтения/записи изменять таблицу.
Итоги
Любая другая транзакция может читать таблицу, зарезервированную текущей транзакцией, причем не существует никаких способов сконфигурировать транзакцию так, чтобы предоставить ей исключительные права на запись для этой таблицы (т. е. все могут читать, если они были сконфигурированы только для чтения и не имеют никаких преимущественных прав на запись). Следующие условия всегда будут блокировать другую транзакцию на чтение из таблицы, зарезервированной текущей транзакцией:
* другая транзакция имеет уровень изоляции SNAPSHOT TABLE STABILITY;
* другая транзакция сконфигурирована на резервирование этой таблицы в режиме PROTECTED WRITE (хотя она может читать эту таблицу, если текущая транзакция зарезервировала ее в режиме SHARED READ);
* другая транзакция собирается зарезервировать эту таблицу в режиме SHARED WRITE, а текущая транзакция зарезервировала ее в режиме PROTECTED READ или PROTECTED WRITE.
В случае если это все еще вам непонятно, посмотрите на рис. 26.1, где некоторые сконфигурированные транзакции сами все расскажут.
Рис. 26.1. Конфигурирование резервирования таблиц