PG中文社区 /

PostgreSQL死锁案例分析(二)

原作者:陈雁飞  创作时间:2019-09-26 15:28:14+08
wangliyun 发布于2019-09-27 08:08:14           评论: 3   浏览: 7992   顶: 676  踩: 752 

作者介绍

陈雁飞,开源PostgreSQL爱好者,一直从事PostgreSQL数据库运维工作

问题现象

接前一篇文章,这里继续介绍在工作中遇到的一个死锁案例。经过对业务模型的抽取分析(后面会介绍表结构和数据,业务模型来源于开源组件的实际业务),模拟得到的死锁日志信息如下:

2019-09-01 21:01:08.359 CST [1482] ERROR:  deadlock detected
2019-09-01 21:01:08.359 CST [1482] DETAIL:  Process 1482 waits for ShareLock on transaction 523; blocked by process 1610.
        Process 1610 waits for ShareLock on transaction 524; blocked by process 1482.
        Process 1482: select test2.a,test2.b,test2.c from test2 join test1 on test2.a = test1.a where test2.b = 2 and test1.c = 3 for update;
        Process 1610: delete from test1 where a = 1;
2019-09-01 21:01:08.359 CST [1482] HINT:  See server log for query details.
2019-09-01 21:01:08.359 CST [1482] CONTEXT:  while locking tuple (0,1) in relation "test1"
2019-09-01 21:01:08.359 CST [1482] STATEMENT:  select test2.a,test2.b,test2.c from test2 join test1 on test2.a = test1.a where test2.b = 2 and test1.c = 3 for update;

从数据库日志上看,记录的SQL语句涉及两张表TEST1和TEST2,其中一个事务执行的SQL是SEELCT … FOR UPDATE用于获取行级锁操作。

流程梳理

经分析,事务操作涉及两张表,简化后的表结构以及操作逻辑如下:

create table test1(a int primary key, b int, c int);
create table test2(a int references test1 on delete cascade,b int, c int);

insert into test1 values(1,2,3),(2,3,4),(3,4,5);
insert into test2 values(1,2,3),(2,3,4),(3,4,5);

表TEST1

CENTER_PostgreSQL_Community

表TEST2

CENTER_PostgreSQL_Community

从表结构上可以看到,表test2和test1构成外键约束关系,并且是级联删除的关系,导致在删除TEST1表中的时候,数据库会自动请求对TEST2表中对应行的删除操作。根据业务操作模型,整理得到的执行SQL逻辑如下(这里仅仅列举出事务中涉及锁相关的操作,其他查询操作未列举出):

CENTER_PostgreSQL_Community

从整理的SQL操作上看,事务一仅仅涉及到对TEST1表的操作,但是由于存在外键级联删除的关系,在delete语句的执行的时候,会请求TEST2表相应的行进行删除。事务二主要是一个SELECT .. FOR UPDATE操作,但是查询语句中涉及两表join关联,且最后锁定的行和事务一中请求的TEST2表相同。因此,可以推测事务二执行的时候,依次涉及对TEST2表和TEST1表的加锁操作。

由于是涉及到行级锁的操作,需要借助gdb工具进行调试,控制事务2获取锁的逻辑顺序。首先,根据执行计划信息,找到加载的行级锁的函数。

CENTER_PostgreSQL_Community

在数据库中,SQL的执行按照生成的执行计划完成的,该执行计划中最顶层算子是LockRows,对应到执行器中的函数是ExecLockRows,结合代码,对行级元素加锁的操作如下:

test = table_tuple_lock(erm->relation, &tid, estate->es_snapshot,
                    markSlot, estate->es_output_cid,
                    lockmode, erm->waitPolicy,
                    lockflags,
                    &tmfd);

因此,使用gdb调试工具在该处函数加上断点,erm记录请求行级锁对应的表信息。操作结果如下:

CENTER_PostgreSQL_Community

可以看到对应表OID为16389,查询数据库该对应的表为TEST2,表明此时事务二已经获取到TEST2对应结果的行级锁信息,此时继续执行事务一中的删除操作,该事务将被阻塞。

CENTER_PostgreSQL_Community

调试工具中继续执行事务二操作之后,出现前文中描述的死锁信息,如下:

CENTER_PostgreSQL_Community

表明事务二中执行的语句先获取TEST2的行锁,然后获取TEST1的行锁,与事务一种的操作获取锁顺序正好相反,由于操作的是相同行,从而导致了死锁发生。

进一步分析

这里查询TEST2对应的语句返回结果只有一条记录,且不需要获取TEST1表中的结果,在手册上对FOR UPDATE锁的解释是“FOR UPDATE causes the rows retrieved by the SELECT statement to be locked as though for update. ”,表示对查询语句检索的行请求锁,这里没有请求TEST1表的数据,为什么也请求该表上的行级锁呢?从直观感觉上看是没有必要的。

其实这个和数据库的执行器获取数据逻辑有关,处理函数为ExecutePlan,在该函数中循环处理每颗Plan并获取对应的所有元组,然后根据前面保存的junk filter信息(ExecFilterJunk函数),获取需要的目标元组。这样,在执行的时候,需要检索Plan中所有表中满足条件的行。

CENTER_PostgreSQL_Community

总结

死锁案例比较简单,并且一般出现在高并发情况下,如果不对业务修改,单纯从数据库角度加锁消除死锁,可能会牺牲并发性能,这一点需要注意。同时,由于行级锁从系统层面无法查看,可以借助gdb等调试工具方式控制行级锁的加载顺序,从而构造出死锁的情况。

CENTER_PostgreSQL_Community


评论:3   浏览: 7992                   顶: 676  踩: 752 

请在登录后发表评论,否则无法保存。

1# __ xcvxcvsdf 回答于 2024-11-11 15:46:01+08
http://fuyang.tjtcbmw.cn/qionghai/ https://bafaliyazhuangyuan.tiancebbs.cn/ http://nalei.zjtcbmw.cn/zhaog/ https://chayuan.tiancebbs.cn/ https://fenlei.tiancebbs.cn/xiangtan/ http://wogao.ahtcbmw.cn/songyuan/ https://xianji.tiancebbs.cn/ http://yz.cqtcxxw.cn/cpq/ http://xinguang.sctcbmw.cn/chengde/ https://zhangfang.tiancebbs.cn/ http://huaguang.jxtcbmw.cn/yqzr/ https://wuhanqk.tiancebbs.cn/ http://xinguang.sctcbmw.cn/luwanqu/ http://km.lstcxxw.cn/yuncheng/ http://gx.lztcxxw.cn/hbes/ http://fuyang.tjtcbmw.cn/heze/ http://xinguang.sctcbmw.cn/shgcheng/

2# __ xcvxcvsdf 回答于 2024-10-23 00:29:06+08
https://su.tiancebbs.cn/hjzl/457879.html https://aihuishou.tiancebbs.cn/sh/4353.html https://zulin.tiancebbs.cn/sh/4877.html https://zulin.tiancebbs.cn/sh/4568.html https://xg.tiancebbs.cn/qths/456415.html https://taicang.tiancebbs.cn/hjzl/458330.html https://as.tiancebbs.cn/qths/473733.html https://sh.tiancebbs.cn/hjzl/465328.html https://zulin.tiancebbs.cn/sh/3252.html https://zulin.tiancebbs.cn/sh/4916.html https://aihuishou.tiancebbs.cn/sh/1077.html https://aihuishou.tiancebbs.cn/sh/1355.html https://changshushi.tiancebbs.cn/hjzl/465373.html https://aihuishou.tiancebbs.cn/sh/4236.html https://su.tiancebbs.cn/hjzl/457906.html https://rizhao.tiancebbs.cn/qths/465517.html https://aihuishou.tiancebbs.cn/store/2775/info-page-301.html

3# __ xiaowu 回答于 2024-04-24 10:38:24+08
地球以什么方式自转:https://www.nanss.com/shenghuo/19388.html 关岛属于哪个国家:https://www.nanss.com/wenti/18487.html 马六甲在哪里:https://www.nanss.com/shenghuo/18475.html 13度天气穿什么衣服合适:https://www.nanss.com/shenghuo/18215.html 珠算口诀表:https://www.nanss.com/shenghuo/19048.html 排骨炖什么好吃又有营养:https://www.nanss.com/yinshi/19487.html 居里夫人读后感:https://www.nanss.com/xuexi/19670.html 欢迎词怎么写:https://www.nanss.com/gongzuo/18824.html 人在作文:https://www.nanss.com/xuexi/19341.html 指南针n代表什么方向:https://www.nanss.com/shenghuo/18205.html 温哥华是哪个国家的:https://www.nanss.com/wenti/18933.html 什么是商务英语:https://www.nanss.com/xuexi/19403.html 阅兵解说词:https://www.nanss.com/xuexi/18379.html 长城导游词:https://www.nanss.com/xuexi/18770.html 八项规定学习心得:https://www.nanss.com/gongzuo/19575.html 政府部门工作总结:https://www.nanss.com/gongzuo/20019.html 碧螺春是什么茶:https://www.nanss.com/yinshi/18969.html 交通工具有哪些:https://www.nanss.com/wenti/19948.html 期末试卷分析:https://www.nanss.com/xuexi/19331.html 森林防火宣传标语:https://www.nanss.com/wenan/20114.html 十月开什么花:https://www.nanss.com/shenghuo/18531.html 日晕代表什么预兆:https://www.nanss.com/wenti/18293.html 加入学生会申请书:https://www.nanss.com/xuexi/18735.html 工作证明英文模板:https://www.nanss.com/gongzuo/18816.html 征兵工作总结:https://www.nanss.com/gongzuo/19810.html 迎新年作文:https://www.nanss.com/xuexi/19201.html 伉俪是什么意思:https://www.nanss.com/wenti/19934.html 致谢怎么写:https://www.nanss.com/xuexi/19808.html 工程质量保修书:https://www.nanss.com/gongzuo/20113.html 送玫瑰:https://www.nanss.com/shenghuo/18996.html



发表评论:
加入我们
QQ群1:5276420
QQ群2:3336901
QQ群3:254622631
文档群:150657323
文档翻译平台:按此访问
社区邮件列表:按此订阅
扫码关注
© PostgreSQL中文社区 ... (自2010年起)