VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

SELECT… FOR UPDATE

功能描述

SELECT … FOR UPDATE语句用于锁定满足WHERE查询条件的行,以防止其他用户在结束事务之前锁定或更新这些行。

注意事项

  • Vastbase数据库中可配置参数“update lockwait timeout”,该参数表示对单个锁的超时时间,默认为 120 秒。当select for update wait integer语句因为加锁需要进行等待时,其中integer值为等待所有行级锁的总计时长,因此,可能在总时长还未达指定值前,该语句因为等待单个行级锁超时而退出并解锁。

  • Vastbase支持FOR UPDATE后跟表或者视图名,不支持跟列名。

  • 该功能仅在数据库兼容模式为Oracle时能够使用(即创建DB时DBCOMPATIBILITY='A'),在其他数据库兼容模式下不能使用该特性。

  • Vastbase G100 V2.2 Build10版本暂不支持的选项为SKIP LOCKED。

  • Vastbase支持FOR UPDATE后跟表或者视图名,语法兼容了后跟列名,支持形如table_name.column_name的写法,但不支持schema.table_name、schema.table_name.column_name。注意仅Vastbase G100 V2.2 Build 10(Patch No.17)及以后版本支持此功能。

语法格式

SELECT ... FOR  UPDATE [ OF table_name | table_name.column_name [, ...] ] [ NOWAIT |
WAIT N | SKIP LOCKED]

参数说明

  • FOR UPDATE

    不跟任何参数:如果当前查询的结果中存在锁,则该查询一直等待(等待期间用户无法执行其他操作),直到查询结果中的锁被释放后,立即返回查询结果。

  • OF table_name

    OF子句用于设定只锁定满足条件的表或行,当前在Vastbase的Oracle兼容模式下,支持在OF子句中指定视图、表和行。

    • 其中OF table_name.column_name指定行仅做了语法兼容,默认识别到表名,忽略字段名。

    • 不支持schema.table_nameschema.table_name.column_name的写法。

    • 仅Vastbase G100 V2.2 Build 10(Patch No.17)及以后版本支持此选项。

  • WAIT N

    如果当前查询的结果中存在锁,且超过N秒后仍未释放锁,则报错,其中N为等待超时时间。

    • N

    取值范围:INT类型,[0, 2147483]。

    取值0:等同NOWAIT。

  • NOWAIT

    当前查询的结果中存在锁,立即报错。

  • SKIP LOCKED

    使用该选项,则忽略有行锁的记录。

示例

1、创建并切换至兼容模式为ORACLE的数据库db_oracle。

CREATE DATABASE db_oracle dbcompatibility=’A’;     
\c db_oracle

2、创建测试表并插入数据。

create table test8(
id number,
orderid number,
productid number,
price number(10,2),
quantity number
);
insert into test8(id,orderid,productid,price,quantity) 
values(1,1,1,6,10),
(2,1,2,4,5),
(3,1,3,10,2),
(4,2,1,3,6),
(5,2,2,4,6);

3、在会话1中,在事务中使用for update加锁,暂不提交。

begin;
select * from test8 where quantity <6 for update;

返回结果为如下:

BEGIN

id | orderid | productid | price | quantity
--------------------------------------------
2 |        1  |          2   | 4 | 5
3 |        1  |          3   | 10 | 2
(2rows)

4、切换至会话2,使用for update nowait 获取同样数据时,提示获取锁失败。

select * from test8 where quantity <6 for update nowait;

返回结果如下:

ERROR:could not obtain lock on row in relation “test8”

5、切换至会话2,使用for update wait 2 获取同样数据,超时(2s)提示获取锁失败。

select * from test8 where quantity <6 for update wait 2;

返回结果如下:

ERROR:  could not obtain lock on row in relation,waitSec = 2000

6、切换至会话2,使用for update wait 600 获取同样数据,n取足够大,阻塞等待会话1事务提交释放锁。

select * from test8 where quantity <6 for update wait 600;

7、切换至会话1,在等待返回结果的600秒内,提交事务,释放锁。

commit;

8、切换至会话2,成功返回查询结果。

id | orderid | productid | price | quantity
--------------------------------------------
2 |        1  |          2   | 4 | 5
3 |        1  |          3   | 10 | 2
(2rows)