首批通过分布式安全可靠测评,为关键业务系统打造
锁表
更新时间:2026-07-15 20:42:45
表锁是最基本的锁定策略,OceanBase 数据库支持对单表、多表以及表的多个一级分区和多个二级分区上锁。
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据库并发控制的一个非常重要的技术。为了确保资源的安全性(也就是数据完整性和一致性)才引申出锁机制。利用其锁机制来实现事务间的数据并发访问及数据一致性。
锁表后,锁定的表将保持锁定状态,直到您提交事务或将事务回滚(回滚到表锁定前的保存点)后,表锁才会被释放。有关事务控制语句的详细说明,请参见 事务控制语句。
表锁模式
OceanBase 数据库当前版本所支持的锁定模式如下:
- ROW SHARE:允许并发访问锁定的表,禁止其他用户锁定整个表而进行独占访问,即禁止其他用户对表上
EXCLUSIVE锁。 - ROW EXCLUSIVE:禁止其他用户在
SHARE及以上(即SHARE,ROW SHARE EXCLUSIVE和EXCLUSIVE)的模式锁定表。在进行更新、插入、删除或进行SELECT FOR UPDATE操作时,将自动获得ROW EXCLUSIVE锁。 - SHARE:允许并发查询,但禁止更新锁定的表。SHARE 锁既会阻止对表内行的更新(
UPDATE,DELETE和INSERT)以及SELECT FOR UPDATE操作,也会阻止对表进行更高级别的锁定,即禁止其他用户对表上SHARE ROW EXCLUSIVE和EXCLUSIVE锁。 - SHARE ROW EXCLUSIVE:允许其他用户查看表中的行,但禁止其更新行(
UPDATE,DELETE和INSERT)及使用SELECT FOR UPDATE查询表中的行,且禁止对表上非ROW SHARE模式的锁。 - EXCLUSIVE:只允许其他用户对锁定的表进行查询,禁止其他用户在表上执行任何类型的 DML 语句或对表上任何类型的锁。
各模式下的锁冲突关系如下表所示:
| 请求锁模式 | 当前锁模式 | |||||
|---|---|---|---|---|---|---|
| ROW SHARE | ROW EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ||
| ROW SHARE | 不冲突 | 不冲突 | 不冲突 | 不冲突 | 冲突 | |
| ROW EXCLUSIVE | 不冲突 | 不冲突 | 冲突 | 冲突 | 冲突 | |
| SHARE | 不冲突 | 冲突 | 不冲突 | 冲突 | 冲突 | |
| SHARE ROW EXCLUSIVE | 不冲突 | 冲突 | 冲突 | 冲突 | 冲突 | |
| EXCLUSIVE | 冲突 | 冲突 | 冲突 | 冲突 | 冲突 | |
权限要求
要锁定的表必须在用户自己的 Schema 中,或者用户必须具有 LOCK ANY TABLE 系统权限。
对整张表上锁
锁定整张表的 SQL 语句如下:
LOCK TABLE [schema.]table_name[,[schema.]table_name ...] IN lockmode MODE [NOWAIT | WAIT integer];
语句使用说明:
table_name:指定待锁定的表的名称,多个表之间使用英文逗号(,)分隔。lockmode:指定表锁模式。NOWAIT | WAIT integer:指定发生锁冲突后的处理方式。如果指定
NOWAIT,当对目标表上锁时发生锁冲突,系统会立即将控制权返回给用户,并返回一条报错信息。如果指定
WAIT integer,当对目标表上锁时发生锁冲突,系统会等待冲突的表锁被释放,直到超过用户设置的语句执行超时时间,若此时该冲突的表锁仍未释放,系统会返回一条报错信息。其中,interger的单位为秒,其值的大小没有限制。注意
当指定
WAIT integer时,语句执行的超时时间取决于integer、ob_query_timeout 及 ob_trx_timeout 的值,并以三者中的最小值作为语句执行的实际超时时间。例如,指定WAIT 10,且ob_query_timeout、ob_trx_timeout均为默认值,则等待锁冲突的超时时间为 1000000 us 即 1s。如果既不指定
NOWAIT也不指定WAIT integer,则语句执行的超时时间将取决于 ob_query_timeout 和 ob_trx_timeout 之间的最小值。
对表 tbl1 上 EXCLUSIVE 锁,示例如下。
LOCK TABLE tbl1 IN EXCLUSIVE MODE NOWAIT;
本示例中,对表 tbl1 上 EXCLUSIVE 锁后,其他用户仅能查询该表,不能在对该表执行任何类型的 DML 语句或对该表再上其他任意类型的锁。
对表的分区上锁
锁定表的分区的 SQL 语句如下:
LOCK TABLE
{
[ schema.]table_name
[ PARTITION '('partition_name ...')' | SUBPARTITION '(' subpartition_name ...')' ] ...
}
IN lockmode MODE
[ NOWAIT | WAIT integer] ;
语句使用说明:
table_name:指定待锁定的分区表的名称。partition_name:指定待锁定的一级分区的分区名。支持同时锁定多个一级分区,分区名之间用英文逗号(,)分隔。subpartition_name:指定待锁定的二级分区的分区名,支持同时锁定多个二级分区,分区名之间用英文逗号(,)分隔。lockmode:指定表锁模式。NOWAIT | WAIT integer:指定发生锁冲突后的处理方式。如果指定
NOWAIT,当对目标表上锁时发生锁冲突,系统会立即将控制权返回给用户,并返回一条报错信息。如果指定
WAIT integer,当对目标表上锁时发生锁冲突,系统会等待冲突的表锁被释放,直到超过用户设置的语句执行超时时间,若此时该冲突的表锁仍未释放,系统会返回一条报错信息。其中,interger的单位为秒,其值的大小没有限制。注意
当指定
WAIT integer时,语句执行的超时时间取决于integer、ob_query_timeout 及 ob_trx_timeout 的值,并以三者中的最小值作为语句执行的实际超时时间。例如,指定WAIT 10,且ob_query_timeout、ob_trx_timeout均为默认值,则等待锁冲突的超时时间为 1000000 us 即 1s。如果既不指定
NOWAIT也不指定WAIT integer,则语句执行的超时时间将取决于 ob_query_timeout 和 ob_trx_timeout 之间的最小值。
下面以示例进行说明。假设当前数据库中有一个模板化二级分区表 tbl2,其建表语句如下。
CREATE TABLE tbl2(col1 NUMBER, col2 NUMBER)
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)
);
创建分区表后,根据模板化二级分区表的分区命名规则,创建的二级分区名分别为 p0ssp0,p0ssp1 和 p0ssp2。有关区命名规则详细说明,请参见 分区概述。
接着对该表进行以下上锁操作:
对表
tbl2的一级分区p1上 EXCLUSIVE 锁。LOCK TABLE tbl2 PARTITION (p1) IN EXCLUSIVE MODE NOWAIT;对表
tbl2的二级分区p1ssp1上 EXCLUSIVE 锁。LOCK TABLE tbl2 SUBPARTITION (p1ssp1) IN EXCLUSIVE MODE WAIT 60;对表
tbl2的一级分区p1、p2和二级分区p2ssp0、p2ssp1上 SHARE 锁。LOCK TABLE tbl2 PARTITION (p1, p2), tbl2 SUBPARTITION (p2ssp0, p2ssp1) IN SHARE MODE;
查看表锁
给表上锁后,可以通过视图 GV$OB_LOCKS 和 V$OB_LOCKS 来查看当前用户各表持锁或请求锁的情况。
SELECT * FROM GV$OB_LOCKS;
查询结果示例。
+----------------+----------+-----------+----------+------+--------+------+-------+---------+-----------+-------+
| SVR_IP | SVR_PORT | TENANT_ID | TRANS_ID | TYPE | ID1 | ID2 | LMODE | REQUEST | CTIME | BLOCK |
+----------------+----------+-----------+----------+------+--------+------+-------+---------+-----------+-------+
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 500003 | NULL | RX | NONE | 462723786 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 500003 | NULL | RS | NONE | 6690958 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200005 | NULL | X | NONE | 462718854 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200006 | NULL | X | NONE | 462710583 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200007 | NULL | X | NONE | 462701111 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200005 | NULL | S | NONE | 6687863 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200006 | NULL | S | NONE | 6679696 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200007 | NULL | S | NONE | 6671395 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200008 | NULL | S | NONE | 6661725 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200009 | NULL | S | NONE | 6653562 | 0 |
| xx.xx.xx.xx | 2882 | 1004 | 1344711 | TM | 200010 | NULL | S | NONE | 6645387 | 0 |
+----------------+----------+-----------+----------+------+--------+------+-------+---------+-----------+-------+
11 rows in set
查询结果中的部分字段说明如下表所示。
| 字段名 | 描述 |
|---|---|
| SRV_IP | 持锁或请求锁的 OBServer 节点的 IP 地址 |
| SRV_PORT | 持锁或请求锁的 OBServer 节点的端口号 |
| TENANT_ID | 持锁或请求锁的租户的 ID |
| TRANS_ID | 持锁或请求锁的事务 ID |
| TYPE | 锁类型:
|
| ID1 | 锁标识符 1:
|
| ID2 | 锁标识符 2:
|
| LMODE | 当前持有锁的模式:
|
| REQUEST | 当前请求锁的模式:
|
| CTIME | 持有或等待锁的时间,单位为微秒 |
| BLOCK | 表示当前事务请求的锁是否被其他事务持有:
|
更多信息
更多 LOCK TABLES 语句的介绍,请参见 LOCK TABLES。