背景
在OceanBase V4.1及之前的版本中,尽管已经为Oracle租户兼容了LOCK TABLE相关的语法,包括单表锁定操作,和WAIT N,
NOWAIT
关键字。但使用时还存在一些限制。例如:LOCK TABLE只能针对单表进行锁定,并不支持多表或分区锁定;WAIT N
和 NOWAIT
关键字在实际执行中并未发挥预期作用,即用户在语句中指定WAIT N
或NOWAIT
后,实际的执行行为和关键字效果不一致,系统仍然会按照设定的语句超时时间和事务超时时间的最小值来等待锁,这意味着锁定操作可能会持续至语句超时或事务超时。
想要了解相关语法和描述可以参考官方文档。LOCK TABLE
在 Oceanbase 4.2 及之后的版本中,提供了更完备的 LOCK TABLE 语法兼容性,并补全了未生效的功能,包括对多表、多分区、多二级分区上锁,以及使WAIT N
和NOWAIT
关键字生效。
LOCK TABLE 语法解析
LOCK TABLE 的语法如下所示:
LOCK TABLE
{
[ schema. ] table
[ PARTITION '('partition ...')' | SUBPARTITION '(' subpartition ...')' ]
...
}
IN lockmode MODE
[ NOWAIT | WAIT integer] ;
其对应的语法结构图如下。
lock_table::=对应的语法结构见下图:
partition_extension_clause::=对应的语法结构见下图:
如果你对上述语法结构中的字段存疑,可以参考下表中对于LOCK TABLE 各字段的说明。
字段名称 | 描述 |
table | 指定要锁定的表的名称。 |
partition | 指定要锁定的分区的名称。 |
subpartition | 指定要锁定的二级分区的名称。 |
lockmode | 指定锁定模式。OceanBase 数据库当前版本支持的锁定模式如下。ROW SHARE:允许并发访问锁定的表,但禁止用户锁定整个表而进行独占访问。ROW EXCLUSIVE :与 ROW SHARE 相同,但也禁止在 SHARE 模式下锁定表。在进行更新、插入或删除时,将自动获得 ROW EXCLUSIVE 锁。SHARE:允许并发查询,但禁止更新锁定的表。SHARE ROW EXCLUSIVE:用于查看整个表,并允许其他人查看表中的行,但禁止其他人在 SHARE 模式下锁定表或更新行。EXCLUSIVE:只允许对锁定的表进行查询,禁止对其进行其他操作。 |
NOWAIT | 如果对执行的表、分区或二级分区上锁时发生锁冲突,则指定 NOWAIT 可以让数据库立即将控制权返回给用户。在这种情况下,数据库会返回一条消息,以告知表、分区或子分区已被另一个用户锁定。 |
WAIT | 如果发生锁冲突,那么语句应该等待冲突的锁释放,直到超过用户设置的 interger 时间(单位对应为秒),integer 的值没有限制。 |
LOCK TABLE 语法实践
了解基本概念和原理后,我们来上手实践一下。以如下所示的表结构作为实践操作表,演示10个操作场景。其中,subpartition template 生成的二级分区名称为一级分区名称 + 's' + 二级分区模板名称
,例如,p0
分区有二级分区p0ssp0
、p0ssp1
和p0ssp2
。
create table test(col1 int, col2 int)
partition by range (col1)
subpartition by range (col2)
subpartition template
(
subpartition sp0 values less than (3),
subpartition sp1 values less than (6),
subpartition sp2 values less than (9)
)
(
partition p0 values less than (100),
partition p1 values less than (200),
partition p2 values less than (300)
);
场景1:对整个表上互斥锁。
lock table test in exclusive mode;
场景2:对一级分区p1
上互斥锁。
lock table test partition (p1) in exclusive mode;
场景3:对二级分区p1ssp1
上互斥锁。
lock table test subpartition (p1ssp1) in exclusive mode;
场景4:在两个客户端上分别对同一个表上锁,其中持锁客户端上互斥锁,请求锁客户端上共享锁。
# conn1
start transaction;
lock table test in exclusive mode;# conn2
start transaction;
set ob_trx_timeout = 10000000000; # 10000 second
set ob_query_timeout = 1000000; # 1 second# client will get error code after 1 second
lock table test in share mode;
ERROR HY000: resource busy and acquire with NOWAIT specified or timeout expired
当 LOCK TABLE 语句不设置WAIT N
/NOWAIT
关键字时,其超时时间将取决于语句超时时间和事务超时时间的最小值,在该例子中即为 1 秒后将报出锁冲突错误。
场景5:在两个客户端上分别对同一个表上表锁,其中持锁客户端上互斥锁,请求锁客户端上共享锁,并使用NOWAIT
关键字。
# conn1
start transaction;
lock table test in exclusive mode;# conn2
start transaction;
lock table test in share mode nowait;
ERROR HY000: resource busy and acquire with NOWAIT specified or timeout expired
当 LOCK TABLE 语句设置了NOWAIT
关键字后,若遇到表锁冲突将会立即报错,并在报错信息中体现“NOWAIT”信息。该报错信息与语句不设置WAIT N
/NOWAIT
关键字不同。
场景6:在两个客户端上分别对同一个表上表锁,其中持锁客户端上互斥锁,请求锁客户端上共享锁,并使用WAIT N
关键字。
# conn1
start transaction;
lock table test in exclusive mode;# conn2
start transaction;# client will get error code after 1 second
lock table test in share mode wait 1;
ERROR HY000: resource busy and acquire with NOWAIT specified or timeout expired
当 LOCK TABLE 语句设置了WAIT N
关键字后,若遇到表锁冲突将会等待N
秒,若N
秒后为解锁将报错,并在报错信息中体现“timeout expired”信息。该报错信息与语句不设置WAIT N
/NOWAIT
关键字不同。
场景7:对一个表的多个分区上互斥锁。
lock table test partition (p1,p2) in exclusive mode;
场景8:对一个表的多个二级分区上互斥锁。
lock table test subpartition (p0ssp1,p1ssp2) in exclusive mode;
场景9:对一个表的多个分区和二级分区上互斥锁。
lock table test partition (p1, p2), test subpartition (p3ssp0, p3ssp1) in exclusive mode;
场景10:对不存在的分区上互斥锁(其中p3
分区不存在,但是p0
分区也不会上锁成功,整条语句将回滚).
lock table test partition (p0, p3) in exclusive mode;
ERROR HY000: Specified partition does not exist
写在最后
LOCK TABLE 语句是生产场景中常用的并发控制手段,可以帮助用户简单高效地实现表级的 ddl / dml 互斥。本文介绍了 OceanBase v4.2 新增的 LOCK TABLE Oracle 语法兼容的新特性,从语法的结构、字段的描述等角度详细解析了该新特性的使用方法,并分享了新特性的场景实践,希望能够帮助大家更“丝滑”地使用该特性,也欢迎大家在评论区分享优化建议、使用体验等。