本文介绍了LOCK语法的简介、参数说明以及示例等内容。

描述

LOCK TABLE获得一个表级锁,必要时会等待任何冲突锁被释放。如果指定了NOWAITLOCK TABLE不会等待以获得想要的锁: 如果它不能立刻得到,该命令会被中止并且发出一个错误。一旦获取到, 该锁会被在当前事务中一直持有(没有UNLOCK TABLE命令,锁总是在事务结束时被释放)。

当一个视图被锁定时,出现在该视图定义查询中的所有关系也将被使用同样的锁模式递归地锁住。

在为引用表的命令自动获取锁时, PolarDB总是尽可能使用最不严格的锁模式。提供LOCK TABLE是用于想要更严格的锁定的情况。例如,假设一个应用运行一个READ COMMITTED 隔离级别的事务, 并且需要确保一个表中的数据在该事务的期间保持稳定。要实现这个目的, 必须在查询之前在表上获得SHARE锁模式。这将阻止并发的数据更改并且确保该表的后续读操作会看到已提交数据的一个稳定视图, 因为SHARE锁模式与写入者所要求的 ROW EXCLUSIVE锁有冲突,并且你的 LOCK TABLE name IN SHARE MODE 语句将等待,直到任何并发持有ROW EXCLUSIVE模式锁的持有者提交或者回滚。因此,一旦得到锁, 就不会有未提交的写入还没有解决。更进一步,在释放该锁之前,任何人都不能开始。

要在运行在REPEATABLE READSERIALIZABLE 隔离级别的事务中得到类似的效果,你必须在执行任何 SELECT或者数据修改语句之前执行 LOCK TABLE语句。一个 REPEATABLE READ或者SERIALIZABLE事务的数据视图将在它的第一个SELECT或者数据修改语句开始时被冻结。在该事务中稍后的一个LOCK TABLE仍将阻止并发写 — 但它不会确保该事务读到的东西对应于最新的已提交值。

如果一个此类事务正要修改表中的数据,那么它应该使用 SHARE ROW EXCLUSIVE锁模式来取代 SHARE模式。这会保证一次只有一个此类事务运行。如果不用这种模式,死锁就可能出现:两个事务可能都要求 SHARE模式,并且都不能获得 ROW EXCLUSIVE模式来真正地执行它们的更新(一个事务所拥有的锁不会冲突,因此一个事务可以在它持有SHARE 模式时获得ROW EXCLUSIVE模式 — 但是如果有其他人持有SHARE模式时则不能)。为了避免死锁,确保所有的事务在同样的对象上以相同的顺序获得锁,并且如果在一个对象上涉及多种锁模式,事务应该总是首先获得最严格的那种模式。

语法

    LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]

    其中 lockmode 可以是以下之一:

        ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
        | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE

参数说明

  • name:要锁定的现有表的名称(可以是模式限定的)。如果在表名前指定 ONLY,只有该表会被锁定。如果没有指定 ONLY,该表和它所有的后续表(如果有)都会被锁定。在表名后可以指定来显式地表示把后续表包括在内。

    命令LOCK TABLE a, b;等效于 LOCK TABLE a; LOCK TABLE b;。这些表会被按照在 LOCK TABLE中指定的顺序被锁定。

  • lockmode:锁模式指定这个锁和哪些锁冲突。

    如果没有指定锁模式,则将使用最严格的模式ACCESS EXCLUSIVE

  • NOWAIT:指定LOCK TABLE不等待任何冲突锁被释放:如果所指定的锁不能立即获得,那么事务就会中止。

说明

LOCK TABLE ... IN ACCESS SHARE MODE要求目标表上的SELECT特权。LOCK TABLE ... IN ROW EXCLUSIVE MODE要求目标表上的INSERTUPDATEDELETETRUNCATE特权。所有其他形式的LOCK要求表级UPDATEDELETETRUNCATE特权。

在该视图上执行锁定的用户必须具有该视图上相应的特权。此外视图的拥有者必须拥有底层基关系上的相关特权,但是执行锁定的用户不需要底层基关系上的任何权限。

LOCK TABLE在事务块外部没有用处:锁将只保持到语句完成。因此如果在事务块外部使用了LOCK,PolarDB会报告错误。使用 BEGIN 和 COMMIT (或者 ROLLBACK )定义事务块。

LOCK TABLE只处理表级锁,因此涉及到 ROW的模式名称在这里都是不当的。这些模式名称应该通常被解读为用户在被锁定表中获取行级锁的意向。还有, ROW EXCLUSIVE模式是可共享的表锁。记住就 LOCK TABLE而言,所有的锁模式都具有相同的语义, 只有模式的冲突规则有所不同。

示例

在将要向外键表中执行插入时在主键表上获得 SHARE锁:

    BEGIN WORK;
    LOCK TABLE films IN SHARE MODE;
    SELECT id FROM films
        WHERE name = 'Star Wars: Episode I - The Phantom Menace';
    -- 如果记录没有被返回就做 ROLLBACK
    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;