暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Postgres死锁问题定位

原创 sg1234 2023-06-13
353


1、死锁是什么?

死锁是指两个或两个以上的事务在执行过程中相互持有对方期待的锁,若没有其他机制,它们都将无法进行下去。

例如,事务1在表A上持有一个排它锁,同时试图请求一个在表B上的排它锁,而事务2已经持有表B的排它锁,同时却在请求表A上的一个排它锁,那么两个事务就都不能执行了。PostgreSQL能够自动侦测到死锁,然后退出其中一个事务,从而允许其他事务执行。


2、死锁发生的条件是什么?

死锁的发生必须具备以下4个必要条件。

·互斥条件:指事务对所分配到的资源加了排它锁,即在一段时间内只能由一个事务加锁占用。如果此时还有其他进程请求排它锁,则请求者只能等待,直至持有排它锁的事务释放排它锁。

·请求和保持条件:指事务已经至少持有了一把排它锁,但又提出了新的排它锁请求,而该资源上的排它锁已被其他事务占有,此时请求被阻塞,但同时它对自己已获得的排它锁又持有不放。

·不剥夺条件:指事务已获得的锁在未使用完之前不能被其他进程剥夺,只能在使用完时由自己释放。

·环路等待条件:指在发生死锁时,必然存在一个事务—资源的环形链,即事务集合{T0,T1,T2,…,Tn}中的T0正在等待T1持有的排它锁;P1正在等待P2持有的排它锁,……,Pn正在等待已被P0持有的排它锁。

理解了死锁的原因,尤其是死锁产生的4个必要条件,就可以最大可能地避免、预防和解除死锁。


3、死锁的解决方案是什么?

1、检测死锁

--查询指定表的oid
select oid from pg_class where relname='t_mytab'; -- t_mytab为你觉得可能死锁的表名

-- 根据oid查询该表正在被执行的进程 pid
select pid from pg_locks where relation='358009'; -- 358009为上述查询到表t_mytab的oid

2、解除死锁

1、检测死锁

--查询指定表的oid
select oid from pg_class where relname='t_mytab'; -- t_mytab为你觉得可能死锁的表名

-- 根据oid查询该表正在被执行的进程 pid
select pid from pg_locks where relation='358009'; -- 358009为上述查询到表t_mytab的oid

3、批量解除
若查询到的Pid记录很多,则你可能需要批量执行。以下语句可以生产批量语句,复制出来执行执行即可。

-- 以下358009为步骤1中查询到的死锁表的oid
select 'select pg_cancel_backend( '''|| pid ||''');' pid from pg_locks where relation='358009'
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论