LOCK
Блокирует таблицу.
Синтаксис
LOCK [TABLE] [ONLY] <table_name> [ * ] [, ...] [IN <lockmode> MODE] [NOWAIT] [MASTER ONLY]
где lockmode может быть:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
Описание
LOCK TABLE получает блокировку на уровне таблицы, ожидая при необходимости снятия конфликтующих блокировок. Если указан NOWAIT, LOCK TABLE не ждет получения нужной блокировки: если блокировку невозможно получить немедленно, команда прерывается и выдается ошибка. Как только блокировка получена, она удерживается до завершения текущей транзакции. Команды UNLOCK TABLE нет; блокировки всегда снимаются в конце транзакции.
При автоматическом получении блокировок для команд, обращающихся к таблицам, Greengage DB всегда использует наименее ограничивающий режим блокировки. Команда LOCK TABLE предназначена для случаев, когда может потребоваться более строгая блокировка. Например, предположим, что приложение выполняет транзакцию на уровне изоляции READ COMMITTED и должно гарантировать, что данные в таблице останутся неизменными на протяжении всей транзакции. Для этого можно получить для таблицы блокировку в режиме SHARE перед обращением к ней. Это предотвратит параллельные изменения данных и обеспечит стабильное представление зафиксированных данных при последующем чтении таблицы, поскольку режим блокировки SHARE конфликтует с блокировкой ROW EXCLUSIVE, запрашиваемой при записи, и LOCK TABLE <table_name> 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. Чтобы избежать взаимоблокировок, убедитесь, что все транзакции получают блокировки одних и тех же объектов в одном и том же порядке, и если для одного объекта задействовано несколько блокировок в разных режимах, то транзакции всегда должны сначала получать наиболее строгую блокировку.
Параметры
| Параметр | Описание |
|---|---|
table_name |
Имя (опционально указанное со схемой) существующей таблицы, которую необходимо заблокировать. Если перед именем таблицы указано Если указано несколько таблиц, таблицы блокируются по одной в порядке, указанном в команде |
lockmode |
Режим блокировки определяет, с какими блокировками будет конфликтовать данная блокировка. Если режим блокировки не указан, используется наиболее строгий режим —
ПРИМЕЧАНИЕ
По умолчанию Greengage DB устанавливает более строгую блокировку |
NOWAIT |
Указывает, что команда |
MASTER ONLY |
Указывает, что при выполнении команды |
Примечания
Для выполнения команды LOCK TABLE … IN ACCESS SHARE MODE требуются права SELECT на целевую таблицу. Для всех остальных типов команды LOCK требуются права UPDATE, DELETE или TRUNCATE на уровне таблицы.
Команда LOCK TABLE бесполезна вне блока транзакции: блокировка будет сохраняться только до завершения операции. Поэтому Greengage DB сообщает об ошибке при попытке применить LOCK вне блока транзакции. Используйте BEGIN и END для определения блока транзакции.
LOCK TABLE может устанавливать только блокировки на уровне таблицы, поэтому имена режимов, включающие ROW, не совсем корректны. Эти названия режимов, как правило, следует понимать как указание на намерение пользователя получить блокировки на уровне строк в заблокированной таблице. Кроме того, учтите, что в режиме ROW EXCLUSIVE устанавливается разделяемая блокировка таблицы. Следует помнить, что все режимы блокировки имеют одинаковую семантику в отношении LOCK TABLE, отличаясь только правилами конфликта режимов. За информацией о том, как получить фактическую блокировку на уровне строки, обратитесь к разделу Выражения блокировки статьи SELECT.
Примеры
Получение блокировки SHARE для таблицы films при добавлении записей в таблицу films_user_comments:
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 для указания уровней параллельного доступа к транзакциям. Greengage DB также поддерживает эту команду.
За исключением режимов блокировки ACCESS SHARE, ACCESS EXCLUSIVE и SHARE UPDATE EXCLUSIVE, режимы блокировки в Greengage DB и синтаксис LOCK TABLE совместимы с режимами, присутствующими в СУБД Oracle.