PostgreSQL死锁案例分析 原作者:陈雁飞 创作时间:2019-09-03 10:56:46+08 |
wangliyun 发布于2019-09-04 08:06:46
![]() ![]() ![]() ![]() ![]() |
作者介绍
陈雁飞,开源PostgreSQL爱好者,一直从事PostgreSQL数据库运维工作
问题现象
在最近的生产环境巡检中,发现一个死锁错误。从日志中看,触发死锁的是对表的相同行操作,最终分析和业务操作有关,不过其中涉及到Postgres数据库的外键更新加锁处理逻辑,下面对这个问题展开详细分析。
数据库日志中记录的死锁日志信息如下
2019-08-24 21:18:35.153 HKT [11832] ERROR: deadlock detected
2019-08-24 21:18:35.153 HKT [11832] DETAIL: Process 11832 waits for ShareLock on transaction 588; blocked by process 1672.
Process 1672 waits for ShareLock on transaction 589; blocked by process 11832.
Process 11832: select * from test2 where a = 1 for update;
Process 1672: update test2 set d = 10 where a = 1;
2019-08-24 21:18:35.153 HKT [11832] HINT: See server log for query details.
2019-08-24 21:18:35.153 HKT [11832] CONTEXT: while locking tuple (0,1) in relation "test2"
2019-08-24 21:18:35.153 HKT [11832] STATEMENT: select * from test2 where a = 1 for update;
检查表结构,a列是test2表的主键,,因此理论上对该行的UPDATE和SELECT .. FOR UDPATE操作不会出现死锁,出现死锁必然和业务场景有关。
流程梳理
分析死锁问题必然要和实际业务操作结合起来,这个问题分析也不例外。
首先从数据库日志中可以看到,死锁的时候等待的是事务中的ShareLock锁,因此和事务操作相关,索引需要获取业务的完整事务操作,可以通过设置数据库的配置参数logminduration_statement=0,采集业务所有操作语句,然后分析相关事务操作中的涉及锁相关的语句和表。
经分析,事务操作涉及两张表,简化后的表结构以及操作逻辑如下:
create table test1(a int primary key, b int);
create table test2(a int primary key,b int references test1(a), c int references test1(a), d int);
insert into test1 values(1,1);
insert into test1 values(2,1);
insert into test2 values(1,1,2,5);
表TEST1
表TEST2
从表结构上可以看到,表test2和test1构成外键约束关系,并且是表test2中一行中两列分别对应表test1中两行。分析业务操作发现,业务每次操作的时候需要操作test2中的同一行的两列,整理得到的执行SQL逻辑如下:
这里整理的SQL是分析后的模拟流程,实际流程中每个事务还有对其他表的查询、插入等实际业务操作,这里为了分析问题不再详细整理出来。
手工按照上面的流程执行操作,发现事2执行到T6时刻,必然会触发死锁,并且如果事务1不执行T5语句(不对同一行更新两次),那么就不会触发死锁。
原因分析
死锁必然是两个或者多个事务之间相互持有锁导致的,而此时事务2仅仅持有TEST1表中A=2的行锁,然后请求TEST2表中A=1的行锁,而事务1持有TEST2表中A=1的行锁,因此事务1请求TEST1表中A=2的行锁。根据主外键的知识,更新TEST2的时候会请求TEST1中对应行的锁信息,从而导致死锁的发生。
细心地读者会发现, T4和T5的更新并没有修改列B或列C的值,且T4时刻的更新可以正常执行,难道是T4时更新不会请求T1上的锁,到T5时更新就请求锁了?
在PostgreSQL中确实是这样,我们知道Postgres的外键是通过触发器实现一致性参考的,更新时候代码逻辑如下:
函数AfterTriggerSaveEvent中
加入触发列表之前调用RIFKeyfkupdcheck_required函数检查,该函数部分实现如下
首先获取元组对应的xmin,判断是否是当前事务产生的,如果是属于当前事务新插入的元组,表示需要触发检查,如果不是当前事务插入的数据,且关联键值没有发生变化,就不需要触发检查。T4时刻的更新属于后面一种情况,不会触发触发检查,但是T5时刻更新属于前一种情况,需要请求表TEST1中的两行锁信息,其中一行正好被事务2锁持有,从而导致死锁的发生。
总结
死锁问题的解决需要结合业务实际操作,针对该问题,建议业务将T3/T6操作提到事务开始地方,这样事务中间就变成串行操作,不会触发死锁,本案例中修改对性能影响也不大。
请在登录后发表评论,否则无法保存。
1# __
xcvxcvsdf 回答于 2024-12-01 22:43:12+08
http://huaguang.jxtcbmw.cn/huaian/
https://botou.tiancebbs.cn/
http://nalei.zjtcbmw.cn/bjhr/
http://taiying.njtcbmw.cn/baicheng/
https://shikangzhen.tiancebbs.cn/
https://benxi.tiancebbs.cn/
http://ruanwen.xztcxxw.cn/bjmtg/
http://shenghuo.china-bbs.com/shminhang/
http://taiying.njtcbmw.cn/baishan/
http://yz.cqtcxxw.cn/shangqiu/
http://ruanwen.xztcxxw.cn/dyqz/
http://jinqiang.ahtcbmw.cn/huainan/
http://huaguang.jxtcbmw.cn/panzhihua/
https://fenlei.tiancebbs.cn/bjdx/
https://zcxintang.tiancebbs.cn/
http://ty.cqtcxxw.cn/yantai/
http://huilong.sctcbmw.cn/yinchuan/
2# __
xiaowu 回答于 2024-04-24 10:37:28+08
南方冬至吃什么:https://www.nanss.com/wenti/18221.html 木薯粉:https://www.nanss.com/yinshi/18893.html 热带雨林的作用:https://www.nanss.com/shenghuo/19441.html 铃儿响叮当教案:https://www.nanss.com/xuexi/18615.html 俄罗斯人口多少:https://www.nanss.com/wenti/19647.html 四级英语作文范文:https://www.nanss.com/xuexi/19239.html 醉翁亭在哪里:https://www.nanss.com/xuexi/18200.html 高渐离简介:https://www.nanss.com/xuexi/19415.html 脐橙的营养价值:https://www.nanss.com/yinshi/19539.html 辞职信怎么写:https://www.nanss.com/gongzuo/19152.html 望闻问切是谁提出来的:https://www.nanss.com/xuexi/18910.html 汽油的密度:https://www.nanss.com/shenghuo/18904.html 顿号的用法:https://www.nanss.com/xuexi/18183.html 复习计划:https://www.nanss.com/xuexi/19148.html 呼啦圈可以减肥吗:https://www.nanss.com/wenti/20004.html 高中德育论文:https://www.nanss.com/gongzuo/19173.html 学生会工作心得:https://www.nanss.com/gongzuo/19644.html 秦始皇简介:https://www.nanss.com/xuexi/19890.html 新教师培训心得体会:https://www.nanss.com/gongzuo/19653.html 客家人是什么意思:https://www.nanss.com/wenti/19777.html 句子赏析:https://www.nanss.com/yulu/20075.html 中学生作文大全:https://www.nanss.com/xuexi/18777.html 铝的密度:https://www.nanss.com/shenghuo/19830.html 热量低的水果:https://www.nanss.com/yinshi/20006.html 市场营销计划书:https://www.nanss.com/gongzuo/19280.html 美国首都是哪个城市:https://www.nanss.com/wenti/19906.html 劲舞团签名:https://www.nanss.com/wenan/19196.html 钉子精神:https://www.nanss.com/shenghuo/18703.html 清炖排骨怎么做最好吃:https://www.nanss.com/yinshi/19841.html 养蚕记:https://www.nanss.com/xuexi/18597.html
发表评论:
扫码关注
© PostgreSQL中文社区 ... (自2010年起)