PostgreSQL 使用advisory lock实现行级读写堵塞

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
云数据库 RDS SQL Server,基础系列 2核4GB
简介:

标签

PostgreSQL , select for update , 读写冲突 , 读写堵塞 , advisory lock


背景

PostgreSQL的读写是不冲突的,这听起来是件好事对吧,读和写相互不干扰,可以数据库提高读写并发能力。

但是有些时候,用户也许想让读写冲突(需求:数据正在被更新或者删除时,不允许被读取)。

那么有方法能实现读写冲突吗?

PostgreSQL提供了一种锁advisory lock,可以实现读写堵塞的功能。

使用advisory lock实现行级读写堵塞

1. 创建表,注意使用一个唯一ID(用于advisory lock)

postgres=# create table ad_test(id int8 primary key, info text, crt_time timestamp);
CREATE TABLE

2. 插入测试数据

postgres=# insert into ad_test values (1,'test',now());
INSERT 0 1

3. 会话1,更新某一条记录

postgres=# begin;
BEGIN
postgres=# update ad_test set info='abc' where id=1;
UPDATE 1

4. 会话2,读这条记录

postgres=# select * from ad_test ;
 id | info |          crt_time          
----+------+----------------------------
  1 | test | 2017-05-07 15:57:42.201804
(1 row)

使用以上常规的方法,读写是不冲突的。

5. 会话1,更新这条记录的同时,使用advisory lock锁住这个ID

postgres=# begin;
BEGIN
postgres=# update ad_test set info='abc' where id=1 returning pg_try_advisory_xact_lock(id);
 pg_try_advisory_xact_lock 
---------------------------
 t
(1 row)

UPDATE 1

6. 会话2,查询这条记录时,使用advisory lock探测这条记录,如果无法加锁,返回0条记录。从而实现读写堵塞(实际上是隔离)。

postgres=# select * from ad_test where id=1 and pg_try_advisory_xact_lock(1);
 id | info | crt_time 
----+------+----------
(0 rows)

使用advisory lock,实现了读写冲突的需求(实际上是让读的会话读不到被锁的记录)。

adlock使用注意

advisory lock锁住的ID,是库级冲突的,所以使用时也需要注意哟。

advisory lock相关函数API的详细介绍

https://www.postgresql.org/docs/9.6/static/explicit-locking.html#ADVISORY-LOCKS

https://www.postgresql.org/docs/9.6/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS

advisory lock的其他应用

1. 《PostgreSQL upsert功能(insert on conflict do)的用法》

2. 《PostgreSQL 无缝自增ID的实现 - by advisory lock》

3. 《PostgreSQL 使用advisory lock或skip locked消除行锁冲突, 提高几十倍并发更新效率》

4. 《聊一聊双十一背后的技术 - 不一样的秒杀技术, 裸秒》

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
2月前
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
167 2
|
6月前
|
存储 SQL 关系型数据库
【MySQL技术内幕】6.1-锁、lock和latch
【MySQL技术内幕】6.1-锁、lock和latch
91 0
|
SQL 关系型数据库 MySQL
Mysql Lock Wait
Mysql Lock Wait
183 0
|
关系型数据库 MySQL 数据库
MySQL报错:Lock wait timeout exceeded; try restarting transaction
MySQL报错:Lock wait timeout exceeded; try restarting transaction
657 0
|
SQL 关系型数据库 MySQL
MySQL报错:1205 Lock wait timeout exceeded; try restarting transaction处理
MySQL报错:1205 Lock wait timeout exceeded; try restarting transaction处理
336 0
|
SQL 关系型数据库 MySQL
【MySQL异常】MySQL事务锁问题----lock wait timeout exceeded; try restarting transaction
【MySQL异常】MySQL事务锁问题----lock wait timeout exceeded; try restarting transaction
403 0
|
SQL 关系型数据库 MySQL
Mysql 异常:Lock wait timeout exceeded; try restarting transaction的解决办法
Mysql 异常:Lock wait timeout exceeded; try restarting transaction的解决办法
328 0
|
SQL 关系型数据库 MySQL
mysql Lock wait timeout exceeded; try restarting transaction解决方案
在测试程序时,打的断点怎么都跳不进去,console一直报 “Lock wait timeout exceeded; try restarting transaction”
170 0
|
存储 运维 Cloud Native
【实操系列】基于AnalyticDB PostgreSQL数据共享实现企业级跨多业务的敏捷分析
云数据仓库AnalyticDB PostgreSQL 版发布了最新自研的云原生架构实例,实现了跨实例间的数据共享能力。允许进行跨实例间的实时数据共享且无需进行数据迁移,可支持构建安全、高效、灵活的数据分析场景。本文介绍了依托数据共享实现云数仓跨多业务实例的敏捷数据分析方案;
【实操系列】基于AnalyticDB PostgreSQL数据共享实现企业级跨多业务的敏捷分析

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版