LOCK
Эта страница переведена при помощи нейросети GigaChat.
LOCK
- блокировка таблицы.
Синтаксис
LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
where lockmode is one of:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
Описание
LOCK TABLE
захватывает блокировку на уровне таблицы, при необходимости ожидая освобождения конфликтующих блокировок. Если указано NOWAIT
, команда LOCK TABLE
не будет ждать получения блокировки: если нужная блокировка не может быть получена немедленно, выполнение прерывается с ошибкой. После получения блокировка удерживается до конца текущей транзакции. Команды UNLOCK TABLE
не существует, блокировки всегда освобождаются в конце транзакции.
Если блокируется представление, то все таблицы, участвующие в запросе, определяющем это представление, также блокируются рекурсивно в том же режиме.
При автоматическом получении блокировок для команд, ссылающихся на таблицы, PostgreSQL всегда использует наименее ограничивающий режим блокировки. Команда LOCK TABLE
используется в ситуациях, когда требуется более строгая блокировка. Например, если приложение выполняет транзакцию на уровне изоляции READ COMMITTED
и нужно гарантировать, что данные в таблице останутся стабильными до конца транзакции, можно захватить блокировку в режиме SHARE
перед выполнением запроса. Это предотвратит одновременные изменения данных и обеспечит, что последующие чтения таблицы увидят стабильную картину зафиксированных данных, так как режим SHARE
конфликтует с режимом ROW EXCLUSIVE
, который используется при записи, и команда LOCK TABLE name IN SHARE MODE
будет ожидать, пока все активные держатели блокировки ROW EXCLUSIVE
не завершат свои транзакции (коммитом или откатом). Таким образом, после получения блокировки не останется незавершенных операций записи, и новые записи не смогут начаться до тех пор, пока блокировка не будет снята.
Для достижения аналогичного эффекта при выполнении транзакции на уровне изоляции REPEATABLE READ
или SERIALIZABLE
, необходимо выполнить оператор LOCK TABLE
перед выполнением любого оператора SELECT
или изменения данных. Представление транзакции REPEATABLE READ
или SERIALIZABLE
о данных будет заморожено, когда начнется ее первый оператор SELECT
или изменение данных. LOCK TABLE
позже в транзакции все равно предотвратит одновременные записи, но он не гарантирует, что прочитанные данные соответствуют самым последним зафиксированным значениям.
Если такая транзакция должна изменять данные в таблице, следует использовать режим SHARE ROW EXCLUSIVE
вместо SHARE
. Это гарантирует, что только одна такая транзакция будет выполняться в данный момент. Без этого может возникнуть взаимоблокировка: две транзакции могут обе получить блокировку SHARE
и затем не смогут получить ROW EXCLUSIVE
для выполнения изменений. Обратите внимание, что блокировки в пределах одной транзакции не конфликтуют друг с другом, поэтому транзакция может получить ROW EXCLUSIVE
, уже удерживая SHARE
— но не сможет, если блокировку SHARE
удерживает кто-то другой.
Чтобы избежать взаимоблокировок, убедитесь, что все транзакции запрашивают блокировки на одни и те же объекты в одинаковом порядке, и если для одного объекта нужны блокировки разных режимов, всегда сначала захватывайте наиболее строгую из них.
Параметры
name
- Имя существующей таблицы, при необходимости дополненное схемой, которую нужно заблокировать. Если указано
ONLY
перед именем таблицы, блокируется только сама таблица. ЕслиONLY
не указано, блокируются таблица и все ее дочерние таблицы (если есть). Также можно явно указать*
после имени таблицы, чтобы явно включить дочерние таблицы в блокировку.Команда
LOCK TABLE a, b;
эквивалентнаLOCK TABLE a; LOCK TABLE b;
. Таблицы блокируются поочередно в порядке, заданном в командеLOCK TABLE
.
lockmode
- Режим блокировки, определяющий, с какими другими режимами он конфликтует.
Если режим блокировки не указан, используется
ACCESS EXCLUSIVE
, наиболее ограничивающий режим.
NOWAIT
- Указывает, что команда
LOCK TABLE
не должна ждать освобождения конфликтующих блокировок: если нужная блокировка не может быть получена немедленно, транзакция прерывается.
Примечания
Для блокировки таблицы пользователь должен иметь соответствующее право доступа к указанной lockmode
. Если пользователю предоставлены привилегии MAINTAIN
, UPDATE
, DELETE
или TRUNCATE
на таблицу, любая lockmode
разрешена. Если пользователю предоставлено разрешение INSERT
на таблицу, разрешено использование ROW EXCLUSIVE MODE
(или менее конфликтного режима). Если пользователю предоставлена привилегия SELECT
на таблицу, допускается использование ACCESS SHARE MODE
.
Пользователь, выполняющий блокировку представления, должен иметь соответствующую привилегию на представление. Кроме того, по умолчанию владелец представления должен иметь соответствующие привилегии на базовые отношения, тогда как пользователю, выполняющему блокировку, не нужны никакие разрешения на базовые отношения. Однако если для представления установлено значение security_invoker
равным true
(смотрите CREATE VIEW), то пользователь, выполняющий блокировку, а не владелец представления, должен иметь соответствующие привилегии для базовых отношений.
LOCK TABLE
не имеет эффекта вне блока транзакций: блокировка будет удерживаться только до завершения оператора. Поэтому PostgreSQL сообщает об ошибке, если LOCK
используется вне блока транзакции. Используйте 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';
-- Do ROLLBACK if record was not returned
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
для указания уровней одновременности транзакций. PostgreSQL также поддерживает это. Смотрите SET TRANSACTION для получения подробной информации.
За исключением режимов блокировки ACCESS SHARE
, ACCESS EXCLUSIVE
и SHARE UPDATE EXCLUSIVE
, режимы блокировки PostgreSQL и синтаксис LOCK TABLE
совместимы с теми, которые присутствуют в Oracle.