PostgreSQL 模拟两个update语句死锁 - 利用扫描方法

简介:

标签

PostgreSQL , 死锁 , update , 模拟


背景

在单条UPDATE中模拟死锁,需要借助扫描方法,以及明确让AB两个会话分别锁定一条记录后再锁定对方已经锁定的记录。

利用批量update的语法以及values子句即可实现,这里利用了嵌套循环,确保被更新的表被多次扫描,并且每次扫描时两个会话更新的记录被错开,达到死锁效果。

同时为了让速度慢下来,使用pg_sleep函数,让每一条更新都放缓1秒。

例子

1、建表

postgres=# create table a (id int primary key, info timestamp);  
CREATE TABLE  

2、写入测试数据

postgres=# insert into a select generate_series(1,10);  
INSERT 0 10  

3、会话1 SQL,执行计划

先锁定ID=2的记录,然后锁定ID=1的记录。

postgres=# explain update a set info=clock_timestamp() from (values (2),(1)) t(id) where a.id=t.id and pg_sleep(1) is not null;  
                                 QUERY PLAN                                    
-----------------------------------------------------------------------------  
 Update on a  (cost=0.15..4.80 rows=2 width=46)  
   ->  Nested Loop  (cost=0.15..4.80 rows=2 width=46)  
         Join Filter: (pg_sleep('1'::double precision) IS NOT NULL)   -- 放缓1秒  
         ->  Values Scan on "*VALUES*"  (cost=0.00..0.03 rows=2 width=32)  -- 按values写的顺序扫描  
         ->  Index Scan using a_pkey on a  (cost=0.15..2.37 rows=1 width=10)  -- 先更新2,再更新1   
               Index Cond: (id = "*VALUES*".column1)  
(6 rows)  

4、会话2 SQL,执行计划,与会话1相反。

先锁定ID=1的记录,然后锁定ID=2的记录。

postgres=# explaIN update a set info=clock_timestamp() from (values (2),(1)) t(id) where a.id=t.id and pg_sleep(1) is not null;  
                                 QUERY PLAN                                    
-----------------------------------------------------------------------------  
 Update on a  (cost=0.15..4.80 rows=2 width=46)  
   ->  Nested Loop  (cost=0.15..4.80 rows=2 width=46)   
         Join Filter: (pg_sleep('1'::double precision) IS NOT NULL)      -- 放缓1秒  
         ->  Values Scan on "*VALUES*"  (cost=0.00..0.03 rows=2 width=32)  -- 按values写的顺序扫描  
         ->  Index Scan using a_pkey on a  (cost=0.15..2.37 rows=1 width=10)  -- 先更新1,再更新2   
               Index Cond: (id = "*VALUES*".column1)    
(6 rows)  

5、模拟死锁

会话1  
  
postgres=# update a set info=clock_timestamp() from (values (2),(1)) t(id) where a.id=t.id and pg_sleep(1) is not null;  
ERROR:  deadlock detected  
DETAIL:  Process 19893 waits for ShareLock on transaction 18613573; blocked by process 9910.  
Process 9910 waits for ShareLock on transaction 18613572; blocked by process 19893.  
HINT:  See server log for query details.  
CONTEXT:  while updating tuple (0,1) in relation "a"  
  
马上发起会话2  
  
postgres=# update a set info=clock_timestamp() from (values (1),(2)) t(id) where a.id=t.id and pg_sleep(1) is not null;  
UPDATE 2  
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
SQL Oracle 关系型数据库
实时计算 Flink版操作报错之往GREENPLUM 6 写数据,用postgresql-42.2.9.jar 报 ON CONFLICT (uuid) DO UPDATE SET 语法有问题。怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
9月前
|
关系型数据库 测试技术 Linux
PostgreSQL配置文件修改及启用方法
总的来说,修改和启用PostgreSQL的配置文件是一个直接而简单的过程。只需要找到配置文件,修改你想要改变的选项,然后重启服务器即可。但是,你需要注意的是,不正确的配置可能会导致服务器性能下降,甚至导致服务器无法启动。因此,在修改配置文件之前,你应该充分理解每个选项的含义和影响,如果可能的话,你应该在测试环境中先进行试验。
727 72
|
SQL 关系型数据库 Linux
在CentOS 6上安装和使用PostgreSQL的方法
在CentOS 6上安装和使用PostgreSQL的方法
286 2
|
SQL 关系型数据库 数据库
postgresql报:ERROR: column “i“ of relation “test“ does not exist LINE 1: UPDATE怎么解决?
解决“ERROR: column "i" of relation "test" does not exist”错误的关键在于核实列名的准确性,修正更新语句,确保列名的引用正确无误,并考虑到任何可能影响列名引用的表别名、大小写、特殊字符或动态SQL生成等因素。通过上述步骤,你应该能有效定位并解决问题,保证SQL语句的正确执行。
1156 0
|
Ubuntu 关系型数据库 数据库
在Ubuntu 18.04上安装和使用PostgreSQL的方法
在Ubuntu 18.04上安装和使用PostgreSQL的方法
332 1
|
Ubuntu 关系型数据库 Linux
在Ubuntu 14.04上安装和使用PostgreSQL的方法
在Ubuntu 14.04上安装和使用PostgreSQL的方法
208 1
|
关系型数据库 Linux 数据库
在CentOS 7上安装和使用PostgreSQL的方法
在CentOS 7上安装和使用PostgreSQL的方法
1962 0
|
SQL 关系型数据库 MySQL
postgresql |数据库 |数据库的常用备份和恢复方法总结
postgresql |数据库 |数据库的常用备份和恢复方法总结
500 0
|
关系型数据库 PostgreSQL
postgresql通过select结果进行update
postgresql通过select结果进行update
237 0
|
SQL NoSQL 关系型数据库
PostgreSQL 准确且快速的数据对比方法
作为一款强大而广受欢迎的开源关系型数据库管理系统,PostgreSQL 在数据库领域拥有显著的市场份额。其出色的可扩展性、稳定性使其成为众多企业和项目的首选数据库。而在很多场景下(开发 | 生产环境同步、备份恢复验证、数据迁移、数据合并等),不同环境中的数据库数据可能导致数据的不一致,因此,进行数据库之间的数据对比变得至关重要。
606 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多