怎么在postgresql中使用for update对行级锁进行测试
创始人
2024-12-27 15:22:23
0次

创建表:

CREATE TABLE db_user
(
 id character varying(50) NOT NULL,
 age integer,
 name character varying(100),
 roleid character varying,
 CONSTRAINT db_user_pkey PRIMARY KEY (id)
)

随便插入几条数据即可。

一、不加锁演示

1、打开一个postgreSQL的SQL Shell或pgAdmin的SQL编辑器窗口,执行:

begin;

select * from db_user where name='lisi';

输出结果:

怎么在postgresql中使用for update对行级锁进行测试

2、再打开一个postgreSQL的SQL Shell或pgAdmin的SQL编辑器窗口,执行:

begin;

select * from db_user where name='lisi';

输出结果:

怎么在postgresql中使用for update对行级锁进行测试

二、加锁演示(for update)

1、打开一个postgreSQL的SQL Shell或pgAdmin的SQL编辑器窗口,执行:

begin;

select * from db_user where name='lisi' for update;

输出结果:

怎么在postgresql中使用for update对行级锁进行测试

2、再打开一个postgreSQL的SQL Shell或pgAdmin的SQL编辑器窗口,执行:

begin;

select * from db_user where name='lisi' for update;

输出结果:

怎么在postgresql中使用for update对行级锁进行测试

查询一直处于执行中状态。

3、第一个窗口执行:

commit;

第二个窗口立即执行查询操作,结果如下:

怎么在postgresql中使用for update对行级锁进行测试

第二个窗口记得提交commit;。

三、加锁演示(for update nowait)

1、打开一个postgreSQL的SQL Shell或pgAdmin的SQL编辑器窗口,执行:

begin;

select * from db_user where name='lisi' for update nowait;

输出结果:

怎么在postgresql中使用for update对行级锁进行测试

2、再打开一个postgreSQL的SQL Shell或pgAdmin的SQL编辑器窗口,执行:

begin;

select * from db_user where name='lisi' for update nowait;

输出结果:

怎么在postgresql中使用for update对行级锁进行测试

不会进行资源等待,返回错误信息。

3、第一个窗口执行:

commit;

提交成功,资源锁释放。

总结:

for update nowait和 for update 都会对所查询到得结果集进行加锁,所不同的是,如果另外一个线程正在修改结果集中的数据,for update nowait 不会进行资源等待,只要发现结果集中有些数据被加锁,立刻返回 “55P03错误,内容是无法在记录上获得锁.

命令说明:

begin;--开启事务

begin transaction;--开启事务

commit;--提交

rollback;--回滚

set lock_timeout=5000;--设置超时时间

注意:

连表查询加锁时,不支持单边连接形式,例如:

select u.*,r.* from db_user u left join db_role r on u.roleid=r.id for update;

支持以下形式,并锁住了两个表中关联的数据:

select u.*,r.* from db_user u, db_role r where u.roleid=r.id for update;

补充:PostgreSQL select for update指定列(兼容oracle)

我们可以使用select for update语句来指定锁住某一张表,在oracle中我们可以在for update语句后指定某一列,用来单独锁定指定列的数据。

oracle例子:

建表:

SQL> create table t1(id int, c2 varchar(20), c3 int, c4 float, c5 float); 
Table created.
SQL> create table t2(id int, c6 int); 
Table created.
SQL> insert into t1 values (1, 'SA_REP', 1, 100, 1); 
1 row created.
SQL> insert into t1 values (1, 'SA_REP123', 1, 100, 1); 
1 row created.
SQL> insert into t2 values (1, 2500);
1 row created.

查询:

我们使用下列查询用来只锁住c4列。

SQL> SELECT e.c3, e.c4, e.c5 
 2   FROM t1 e JOIN t2 d 
  USING (id) 
  WHERE c2 = 'SA_REP' 
  AND c6 = 2500 
 3  4  5  6   FOR UPDATE OF e.c4 
 7   ORDER BY e.c3; 
    C3     C4     C5
---------- ---------- ----------
     1    100     1

PostgreSQL兼容方法:

建表:

create table t1(id int, c2 text, c3 int, c4 float, c5 float); 
create table t2(id int, c6 int); 
insert into t1 values (1, 'SA_REP', 1, 100, 1); 
insert into t1 values (1, 'SA_REP123', 1, 100, 1); 
insert into t2 values (1, 2500);

pg中使用方法和oracle类似,只是需要将order by语法放到前面,并且将列名换成表名。

bill=# SELECT e.c3, e.c4, e.c5 
bill-#  FROM t1 e JOIN t2 d 
bill-#  USING (id) 
bill-#  WHERE c2 = 'SA_REP' 
bill-#  AND c6 = 2500 
bill-#  ORDER BY e.c3
bill-#  FOR UPDATE OF e ;
 c3 | c4 | c5 
----+-----+----
 1 | 100 | 1
(1 row)

验证:

我们可以验证下pg中是否只锁定了指定的行。

1、安装pgrowlocks插件

bill=# create extension pgrowlocks;

CREATE EXTENSION

2、观察

t1表被锁:

bill=# select * from pgrowlocks('t1'); 
 locked_row | locker | multi | xids |   modes   | pids 
------------+--------+-------+--------+----------------+--------
 (0,1)   |  1037 | f   | {1037} | {"For Update"} | {2022}
(1 row)

t2表没有被锁:

bill=# select * from pgrowlocks('t2');  
 locked_row | locker | multi | xids | modes | pids 
------------+--------+-------+------+-------+------
(0 rows)

我们还可以再看看t1表中具体被锁住的数据:

bill=# SELECT * FROM t1 AS a, pgrowlocks('t1') AS p 
bill-#  WHERE p.locked_row = a.ctid; 
 id |  c2  | c3 | c4 | c5 | locked_row | locker | multi | xids |   modes   | pids 
----+--------+----+-----+----+------------+--------+-------+--------+----------------+--------
 1 | SA_REP | 1 | 100 | 1 | (0,1)   |  1037 | f   | {1037} | {"For Update"} | {2022}
(1 row)

除此之外,pg中for update子句还有其它的选项:

UPDATE – 当前事务可以改所有字段

NO KEY UPDATE – 当前事务可以改除referenced KEY以外的字段

SHARE – 其他事务不能改所有字段

KEY SHARE – 其他事务不能改referenced KEY字段

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...