LOCK#
LOCK
LOCK — заблокировать таблицу
Синтаксис
LOCK [ TABLE ] [ ONLY ]name
[ * ] [, ...] [ INlockmode
MODE ] [ NOWAIT ] wherelockmode
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
нет; блокировки всегда освобождаются при завершении транзакции).
Когда представление заблокировано, все отношения, указанные в запросе определения представления, также блокируются рекурсивно с тем же режимом блокировки.
При автоматическом получении блокировок для команд, которые обращаются к таблицам, Tantor SE всегда использует наименее ограничительный режим блокировки. Команда LOCK TABLE
предусматривает случаи, когда вам может понадобиться более ограничительная блокировка. Например, предположим, что приложение выполняет транзакцию на уровне изоляции READ COMMITTED
и требуется обеспечить стабильность данных в таблице на протяжении всей транзакции. Для этого вы можете получить режим блокировки SHARE
над таблицей перед выполнением запроса. Это предотвратит одновременные изменения данных и обеспечит последующие чтения таблицы в стабильном виде уже зафиксированных данных, поскольку режим блокировки SHARE
конфликтует с режимом блокировки ROW EXCLUSIVE
, получаемым писателями, и ваш оператор LOCK TABLE
будет ожидать, пока все одновременные держатели блокировок в режиме name
IN SHARE MODEROW EXCLUSIVE
подтвердятся или откатят свои транзакции. Таким образом, после получения блокировки не остается неподтвержденных записей; кроме того, ни одна новая запись не может быть начата до освобождения блокировки.
Чтобы достичь аналогичного эффекта при выполнении транзакции на уровне изоляции REPEATABLE READ
или SERIALIZABLE
, необходимо выполнить оператор LOCK TABLE
перед выполнением любого оператора SELECT
или модификации данных. Представление данных в транзакции с уровнем изоляции REPEATABLE READ
или SERIALIZABLE
будет заморожено, когда начинается первый оператор SELECT
или модификации данных. Оператор LOCK TABLE
, выполненный позже в транзакции, все еще будет предотвращать одновременные записи, но это не гарантирует, что данные, которые транзакция считывает, соответствуют последним зафиксированным значениям.
Если транзакция такого типа собирается изменять данные в таблице, то она должна использовать режим блокировки SHARE ROW EXCLUSIVE
вместо режима SHARE
. Это гарантирует, что только одна транзакция этого типа выполняется одновременно. Без этого возможна блокировка: две транзакции могут оба получить режим SHARE
, а затем не могут получить режим ROW EXCLUSIVE
для выполнения своих обновлений. (Обратите внимание, что блокировки собственных транзакций никогда не конфликтуют, поэтому транзакция может получить режим ROW EXCLUSIVE
, когда она удерживает режим SHARE
- но не если кто-то другой удерживает режим SHARE
). Чтобы избежать блокировок, убедитесь, что все транзакции получают блокировки на одних и тех же объектах в том же порядке, и если для одного объекта используются несколько режимов блокировки, то транзакции всегда должны сначала получать наиболее ограничительный режим.
Более подробную информацию о режимах блокировки и стратегиях блокировки можно найти в Раздел 13.3.
Параметры
name
Имя (опционально с указанием схемы) существующей таблицы для блокировки. Если перед именем таблицы указано
ONLY
, блокируется только эта таблица. ЕслиONLY
не указано, блокируется таблица и все ее потомки (если они есть). Дополнительно, после имени таблицы можно указать*
, чтобы явно указать, что включены потомки.Команда
LOCK TABLE a, b;
эквивалентнаLOCK TABLE a; LOCK TABLE b;
. Таблицы блокируются по одной в порядке, указанном в командеLOCK TABLE
.lockmode
Спецификация режима блокировки определяет, с какими блокировками конфликтует данная блокировка. Режимы блокировки описаны в Раздел 13.3.
Если не указан режим блокировки, то используется наиболее ограничительный режим
ACCESS EXCLUSIVE
.NOWAIT
Указывает, что
LOCK TABLE
не должен ожидать освобождения каких-либо конфликтующих блокировок: если указанные блокировки не могут быть немедленно получены без ожидания, транзакция прерывается.
Примечания
LOCK TABLE ... IN ACCESS SHARE MODE
требует наличия привилегий SELECT
на целевую таблицу. LOCK TABLE ... IN ROW EXCLUSIVE MODE
требует наличия привилегий INSERT
, UPDATE
, DELETE
или TRUNCATE
на целевую таблицу. Все остальные формы команды LOCK
требуют наличия привилегий UPDATE
, DELETE
или TRUNCATE
на уровне таблицы.
Пользователь, выполняющий блокировку представления, должен иметь соответствующие привилегии на представление. Кроме того, по умолчанию владелец представления должен иметь соответствующие привилегии на базовые отношения, в то время как пользователь, выполняющий блокировку, не требуется иметь какие-либо разрешения на базовые отношения. Однако, если у представления установлено значение true
для security_invoker
(см. CREATE VIEW
), пользователь, выполняющий блокировку, а не владелец представления, должен иметь соответствующие привилегии на базовые отношения.
LOCK TABLE
бесполезна вне блока транзакции: блокировка будет сохранена только до завершения оператора. Поэтому Tantor SE сообщает об ошибке, если LOCK
используется вне блока транзакции.
Используйте BEGIN
и COMMIT
(или ROLLBACK
) для определения блока транзакции.
LOCK TABLE
занимается только блокировкой на уровне таблицы, поэтому имена режимов, связанные с ROW
, являются неправильными. Эти имена режимов, как правило, следует понимать как указание пользователю о намерении получить блокировку на уровне строк внутри заблокированной таблицы. Кроме того, режим ROW EXCLUSIVE
является долевой блокировкой таблицы. Имейте в виду, что все режимы блокировки имеют идентичную семантику в отношении LOCK TABLE
, отличаясь только правилами конфликта между режимами. Для получения информации о том, как получить фактическую блокировку на уровне строк, см. Раздел 13.3.2 и The Locking Clause в документации 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
для указания уровней параллелизма в транзакциях. Tantor SE также поддерживает эту функцию; см. SET TRANSACTION для получения подробной информации.
За исключением режимов блокировки ACCESS SHARE
, ACCESS EXCLUSIVE
и SHARE UPDATE EXCLUSIVE
, режимы блокировки Tantor SE и синтаксис LOCK TABLE
совместимы с режимами блокировки, присутствующими в Oracle.