源码论坛公告:本站是一个交流学习建站资源的社区论坛,旨在交流学习源码脚本等资源技术,欢迎大家投稿发言! 【点击此处将锦尚放在桌面

源码论坛,商业源码下载,尽在锦尚中国商业源码论坛

 找回密码
 会员注册

QQ登录

只需一步,快速开始

查看: 5054|回复: 0
打印 上一主题 下一主题

[Mysql教程] PostgreSQL死锁了怎么办及处理方法

[复制链接]

3102

主题

3503

帖子

13万

金币

超级版主

Rank: 8Rank: 8

积分
271670
跳转到指定楼层
1#
发表于 2023-1-17 21:04:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

这篇文章主要介绍了PostgreSQL死锁了怎么办?本文给大家讲解了死锁原因及解决方法,介绍l避免死锁的实战建议,本文给大家介绍的非常详细,需要的朋友可以参考下


什么是数据库死锁

在操作系统领域当中,死锁指的是两个或者两个以上的进程在运行的过程中,因为争夺共同的访问资源而相互等待阻塞,最终造成阻碍进程继续执行的一种阻塞现象。那么在数据库领域当中死锁又是怎样的表现形式呢?

如下图所示,假设事务A持有行1的共享锁,事务B持有行2的共享锁,那么此时事务A请求持有行2的排他锁,那么在事务B释放资源之前都处于阻塞等待的状态,同样的事务B请求持有行1的排他锁,在事务A 释放资源之前同样也是处于阻塞等待的状态。也就是说事务 B 完成之后事务 A 才能完成,而事务A的完成又依赖于事务B的完成,这就形成了循环依赖的问题,最终导致死锁情况的发生。



如何确定死锁位置

  1. //先确定数据库有没有死锁情况发生
  2. select * from pg_stat_activity where datname = 'product_db';

  3. //查询可能锁了的表的oid
  4. select oid from pg_class where relname='product';

  5. //查询对应的pid
  6. select pid from pg_locks where relation='oid'  //上面查询出来的oid

  7. //取消或者终止对应的进程
  8. select pg_cancel_backend(pid);
  9. select pg_terminate_backend(pid);
复制代码


死锁的可能原因以及解决办法

以上分析了PostgreSQL出现死锁后如何定位分析,那么接下来就需要总结分析分析下数据库出现死锁情况的原因以及一般的应对解决办法。

1、索引使用问题导致的死锁问题

索引使用存在问题的话会导致死锁问题,假设在一个数据查询的事务当中,进行数据检索的时候没办法按照SQL中的where条件进行查询,因此导致了全表扫描,那么此时数据库表的行级锁会上升为表级锁。如果此时有多个未能按照where条件进行数据查询的事务存在,那么就容易导致数据库死锁问题。也就是说在数据库表数据量比较大的时候,对应进行数据查询的表没有建立索引或者说索引创建的不合理导致无法通过索引进行数据查询,只能通过全表索引,这样的场景下就容易产生死锁。

如何避免:

在进行数据查询的时候,对应的SQL语句不宜太过复杂,也就是说尽量避免多张表的关联查询。

2、不同事务之间的访问顺序问题

当用户A 访问数据库表A时,此时对表A加了共享锁,然后又访问数据库表B。而此时另一个用户B 访问表B,对表B加了共享锁,然后试图访问表A。但是用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,也就是说互相等待对方释放资源,从而导致了死锁的发生。

如何避免:

这种情况在实际项目中遇到的可能比较多,主要还是需要通过控制代码的执行逻辑,避免多表操作时同时锁住多个资源。

避免死锁的实战建议

(1)如果平台中存在大事务,尽量将其拆分为小事务。因为大事务一般操作的数据库表或者数据都比较多,因此造成死锁或者阻塞的概率就会相对较大。

(2)为数据库表设计合理的索引,尽量避免数据查询时索引未覆盖或者索引失效的情况,因为全表扫描会会导致给表中的数据行上锁,大大增加了数据库产生死锁的概率。

(3)如果业务允许,我们可以尝试将隔离级别调低,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。

补充:下面在看下Postgresql死锁的处理

背景:

对表进行所有操作都卡住,原因可能是更新表时导致这个表死锁了,开始进行排查

解决一:查询pg_stat_activity有没有记录

pg版本10.2

  1. select pid,query,* from pg_stat_activity where datname='死锁的数据库' and wait_event_type = 'Lock';
  2. select pg_cancel_backend('死锁那条数据的pid值');##只能杀死select 语句, 对其他语句不生效
  3. pg_terminate_backend('死锁那条数据的pid值');#select,drop等各种操作
复制代码


执行后发现select和delete表时正常执行,但truncate和drop表时会一直运行,也不报错。

“drop table” 和 “truncate table” 需要申请排它锁"ACCESS EXCLUSIVE", 执行这个命令卡住时,说明此时这张表上还有操作正在进行,比如查询等,

那么只有等待这个查询操作完成,“drop table” 或"truncate table"或者增加字段的SQL才能获取这张表上的 "ACCESS EXCLUSIVE"锁,操作才能进行下去。

解决二:查询pg_locks是否有这个对象的锁

  1. select oid,relname from pg_class where relname='table name';
  2. select locktype,pid,relation,mode,granted,* from pg_locks where relation= '上面查询出来的oid';
  3. select pg_terminate_backend('进程ID');
复制代码


问题解决!!!

坑:一开始不知道pg_cancel_backend(‘死锁那条数据的pid值');##只能杀死select 语句, 对其他语句不生效,杀了进程查询发现还存在,反复杀反复存在,换了pg_terminate_backend(‘进程ID')问题就解决了。

PS:postgresql表死锁问题的排查方式

1.查询激活的执行中的sql,查看有哪些更新update的sql。

  1. select *
  2. from pg_stat_activity
  3. where state = 'active';
复制代码


2. 查询表中存在的锁

  1. select a.locktype, a.database, a.pid, a.mode, a.relation, b.relname
  2. from pg_locks a
  3. join pg_class b on a.relation = b.oid
  4. where lower(b.relname) = 'h5_game';
复制代码


3. 杀掉死锁进程

  1. select pg_terminate_backend(pid)
  2. from pg_stat_activity
  3. where state = 'active'
  4. and pid != pg_backend_pid()
  5. --and pid = 14172
  6. and pid in (select a.pid
  7. from pg_locks a
  8. join pg_class b on a.relation = b.oid
  9. where lower(b.relname) = 'news_content')
复制代码


锁模式

  1. /* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
  2. #define NoLock                 0

  3. #define AccessShareLock         1        /* SELECT */
  4. #define RowShareLock          2        /* SELECT FOR UPDATE/FOR SHARE */
  5. #define RowExclusiveLock        3        /* INSERT, UPDATE, DELETE */
  6. #define ShareUpdateExclusiveLock 4       /* VACUUM (non-FULL),ANALYZE, CREATE
  7.                                          * INDEX CONCURRENTLY */
  8. #define ShareLock                5        /* CREATE INDEX (WITHOUT CONCURRENTLY) */
  9. #define ShareRowExclusiveLock  6        /* like EXCLUSIVE MODE, but allows ROW
  10.                                          * SHARE */
  11. #define ExclusiveLock          7        /* blocks ROW SHARE/SELECT...FOR
  12.                                          * UPDATE */
  13. #define AccessExclusiveLock       8        /* ALTER TABLE, DROP TABLE, VACUUM
  14.                                          * FULL, and unqualified LOCK TABLE */
复制代码


到此这篇关于PostgreSQL死锁了怎么办?的文章就介绍到这了,更多相关PostgreSQL死锁内容请搜索源码论坛以前的文章或继续浏览下面的相关文章希望大家以后多多支持源码论坛!

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享
您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

锦尚中国源码论坛

聚合标签|锦尚中国,为中国网站设计添动力 ( 鲁ICP备09033200号 ) |网站地图

GMT+8, 2024-4-25 20:38 , Processed in 0.029561 second(s), 16 queries .

带宽由 锦尚数据 提供 专业的数据中心

© 锦尚中国源码论坛 52jscn Inc. 非法入侵必将受到法律制裁 法律顾问:IT法律网 & 褚福省律师 锦尚爱心 版权申诉 版权与免责声明