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.