LOCK
LOCK — заблокировать таблицу
Синтаксис
LOCK [ TABLE ] [ ONLY ] имя [ * ] [, ...][ IN режим_блокировки ] [ NOWAIT ]
где режим_блокировки является одним из следующих:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
Описание
LOCK TABLE
получает блокировку уровня таблицы, при необходимости ожидая
освобождения всех конфликтующих блокировок. Если указывается NOWAIT,
LOCK TABLE
не ожидает освобождения таблицы: если блокировку нельзя получить немедленно, команда
прерывается и выдается ошибка. После получения блокировка удерживается до конца
текущей транзакции. (Команды UNLOCK TABLE
не существует; блокировки всегда
освобождаются в конце транзакции.)
Когда блокируется представление, все отношения, появляющиеся в запросе определения представления, также рекурсивно блокируются с тем же режимом блокировки.
При автоматическом получении блокировок для команд, ссылающихся на
таблицы, QHB всегда использует наименее ограничительный режим
блокировки. Команда LOCK TABLE
предназначена для случаев, когда
может потребоваться более строгая блокировка. Например, предположим, что
приложение выполняет транзакцию на уровне изоляции READ COMMITTED
и должно обеспечить неизменность данных в таблице на протяжении всей транзакции.
Для этого можно перед запросом получить над таблицей блокировку в режиме SHARE.
Это предотвратит одновременные изменения данных и обеспечит стабильное представление зафиксированных данных при последующем
чтении таблицы, потому что режим блокировки SHARE конфликтует с запрашиваемой при записи
блокировкой ROW EXCLUSIVE, а команда LOCK TABLE имя IN SHARE MODE
будет ждать, пока
все параллельные транзакции с блокировкой ROW EXCLUSIVE не будут зафиксированы или отменены.
Таким образом, в момент получения такой блокировки
не останется никаких открытых незафиксированных операций записи; более
того, до снятия блокировки никто не сможет записывать в таблицу.
Для достижения аналогичного эффекта при выполнении транзакции на
уровнях изоляции REPEATABLE READ или SERIALIZABLE нужно
выполнить команду LOCK TABLE
перед выполнением первой команды
SELECT
или команды, изменяющей данные.
Представление данных для транзакции уровня REPEATABLE READ или
SERIALIZABLE будет заморожено в момент, когда начнет выполняться этот запрос.
Если команда LOCK TABLE
выполняется в транзакции позже, она также исключает
параллельную запись, но не гарантирует, что транзакция будет считывать
последние зафиксированные значения.
Если транзакция такого рода будет изменять данные в таблице, следует использовать режим блокировки SHARE ROW EXCLUSIVE вместо SHARE. Это гарантирует, что в один момент времени будет выполняться только одна транзакция такого типа. Без этого ограничения возможна взаимная блокировка: обе транзакции могут получить блокировки SHARE, после чего не смогут получить блокировку ROW EXCLUSIVE, чтобы выполнить изменения. (Обратите внимание, что собственные блокировки транзакции никогда не конфликтуют, поэтому транзакция может получить блокировку ROW EXCLUSIVE, когда владеет блокировкой SHARE — но не тогда, когда блокировку SHARE удерживает другая транзакция.) Чтобы избежать взаимоблокировок, убедитесь, что все транзакции запрашивают блокировки одних и тех же объектов в одном и том же порядке, и если для одного объекта запрашиваются блокировки с разными режимами, то транзакции всегда должны сначала запрашивать наиболее строгую блокировку.
Дополнительную информацию о режимах и стратегиях блокировки можно найти в разделе Явная блокировка.
Параметры
имя
Имя существующей таблицы, подлежащей блокировке (может быть дополнено схемой). Если перед именем таблицы указывается ONLY, то блокируется только эта таблица. Если ONLY не указан, то блокируются таблица и все ее потомки (если таковые имеются). После имени таблицы можно добавить необязательное указание *, чтобы явно обозначить, что включены и все дочерние таблицы.
Команда LOCK TABLE a, b;
эквивалентна LOCK TABLE a; LOCK TABLE b;
. Таблицы блокируются одна за другой
в порядке, указанном в команде LOCK TABLE
.
режим блокировки
Режим блокировки определяет, с какими блокировками эта блокировка конфликтует. Режимы блокировки описаны в разделе Явная блокировка.
Если режим блокировки не указан, то применяется самый строгий режим ACCESS EXCLUSIVE.
NOWAIT
Указывает, что LOCK TABLE
не должна ожидать освобождения
конфликтующих блокировок: если указанные блокировки не могут быть
получены немедленно без ожидания, транзакция прерывается.
Примечания
Команда LOCK TABLE ... IN ACCESS SHARE MODE
требует права SELECT к целевой таблице.
Команда LOCK TABLE ... IN ROW EXCUSIVE MODE
требует прав INSERT, UPDATE,
DELETE или TRUNCATE к целевой таблице. Все другие формы LOCK
требуют
прав UPDATE, DELETE или TRUNCATE к целевой таблице.
Пользователь, выполняющий блокировку представления, должен иметь соответствующие права для этого представления. Кроме того, владелец представления должен иметь соответствующие права доступа к нижележащим базовым отношениям, но пользователь, выполняющий блокировку, не нуждается в каких-либо правах на базовые отношения.
LOCK TABLE
бесполезна вне блока транзакций: блокировка будет
удерживаться только до завершения операции. Поэтому если LOCK
используется вне блока
транзакций, QHB сообщает об ошибке.
Для определения блока транзакций используйте команды BEGIN и COMMIT (или ROLLBACK).
LOCK TABLE
имеет дело только с блокировками уровня таблицы, и
поэтому имена режимов, включающие ROW, не вполне корректны.
Эти имена режимов обычно следует рассматривать как указывающие на намерение
пользователя получить блокировки на уровне строк в заблокированной
таблице. Кроме того, ROW EXCLUSIVE — это разделяемая блокировка
таблицы. Имейте в виду, что для LOCK TABLE
все режимы блокировки имеют одинаковую
семантику, отличаясь только правилами, определяющими, какие режимы конфликтуют друг с другом.
Информацию о том, как получить фактическую блокировку уровня
строки, см. в разделах Блокировка на уровне строк
и Предложение блокировки в справочной документации по команде SELECT.
Примеры
Получение блокировки SHARE для первичного ключа таблицы при выполнении операций добавления в подчиненную таблицу:
BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- Будет выполнен откат, если запись не будет возвращена
INSERT INTO films_user_comments VALUES
(id, 'GREAT! I was waiting for it for so long!');
COMMIT WORK;
Установка блокировки SHARE ROW EXCLUSIVE в таблице первичного ключа перед выполнением операции удаления:
BEGIN WORK;
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM films_user_comments WHERE id IN
(SELECT id FROM films WHERE rating < 5);
DELETE FROM films WHERE rating < 5;
COMMIT WORK;
Совместимость
В стандарте SQL нет команды LOCK TABLE
; вместо этого для указания уровней изоляции в транзакциях
в нём используется команда SET TRANSACTION
.
QHB поддерживает и этот вариант; дополнительную информацию см. в
разделе SET TRANSACTION.
За исключением ACCESS SHARE, ACCESS EXCLUSIVE и SHARE UPDATE EXCLUSIVE,
режимы блокировки и синтаксис команды LOCK TABLE
в QHB
совместимы с имеющимися в СУБД Oracle.