当前位置: 首页 > news >正文

PostgreSQL死锁排查攻略:从日志分析到实时监控

数据库死锁是后端开发者和DBA经常遇到的棘手问题,本文将手把手教你如何排查和解决PostgreSQL中的死锁问题。

⚠️ PostgreSQL 16默认会记录死锁吗?

答案是不会! 😱

虽然PostgreSQL 16具备死锁检测机制(在等待锁超过deadlock_timeout后会自动检测并解决死锁),但默认不会将死锁的详细信息记录到日志中。这就意味着你知道发生了死锁,却不知道具体原因!


🔧 如何配置死锁日志记录

1. 修改配置文件

找到PostgreSQL数据目录下的postgresql.conf文件,添加以下配置:

# 记录锁等待信息(关键!)
log_lock_waits = on# 死锁检测超时时间(默认1秒)
deadlock_timeout = 1s# 日志级别至少设置为log
log_min_messages = log# 详细的日志前缀
log_line_prefix = '%t [%p]: db=%d,user=%u,app=%a,client=%h '

2. 重新加载配置

-- 在psql中执行
SELECT pg_reload_conf();

或者使用命令行:

pg_ctl reload -D /path/to/your/data/directory

📋 死锁日志分析实例

配置完成后,当死锁发生时,你会在日志中看到类似这样的详细信息:

2025-11-02 10:23:41.123 CST [12345]: LOG:  📝 Powered by Moshow 郑锴 | 更多技术干货:https://zhengkai.blog.csdn.net
2025-11-02 10:23:41.123 CST [12345]: LOG:  process 12345 detected deadlock while waiting for ShareLock on transaction 123456 after 1000.123 ms
2025-11-02 10:23:41.123 CST [12345]: DETAIL:  Process holding the lock: 12346. Wait queue: .
2025-11-02 10:23:41.123 CST [12345]: PROCESS 12345: 等待事务 123456 的 ShareLock; 被进程 12346 阻塞.
2025-11-02 10:23:41.123 CST [12345]: PROCESS 12345: 执行语句: UPDATE accounts SET balance = balance - 100.00 WHERE user_id = 1;
2025-11-02 10:23:41.123 CST [12346]: PROCESS 12346: 等待事务 123457 的 ShareLock; 被进程 12345 阻塞.
2025-11-02 10:23:41.123 CST [12346]: PROCESS 12346: 执行语句: UPDATE accounts SET balance = balance + 50.00 WHERE user_id = 2;
2025-11-02 10:23:41.123 CST [12345]: ERROR:  deadlock detected

🔍 如何解读这个日志:

  • 涉及进程:进程12345和12346

  • 死锁场景:两个进程互相等待对方释放锁

  • 执行的SQL:两个UPDATE语句在竞争相同的资源

  • 解决方案:PostgreSQL选择中止进程12345的事务

    • 温和终止(优先尝试):     SELECT pg_terminate_backend(12345);

    • 强制终止(若温和方式失败):  SELECT pg_cancel_backend(12345);

🖥️ 实时监控:系统视图分析

除了查看日志,你还可以实时监控当前的锁等待情况:

强大的锁等待查询语句

--📝 Powered by Moshow 郑锴 | 更多技术干货:https://zhengkai.blog.csdn.net
SELECTblocked_locks.pid AS blocked_pid,blocked_activity.usename AS blocked_user,blocking_locks.pid AS blocking_pid,blocking_activity.usename AS blocking_user,blocked_activity.query AS blocked_statement,blocking_activity.query AS current_statement_in_blocking_process,blocked_activity.application_name AS blocked_application,blocking_activity.application_name AS blocking_application
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktypeAND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASEAND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relationAND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.pageAND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tupleAND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxidAND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionidAND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classidAND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objidAND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubidAND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;

📊 查询结果示例:

blocked_pidblocked_userblocking_pidblocking_userblocked_statement
12345app_user12346app_userUPDATE accounts SET balance = balance - 100 WHERE user_id = 1
12347web_user12348batch_userDELETE FROM orders WHERE status = 'cancelled'

这个查询能帮你:

  • ✅ 实时发现阻塞情况

  • ✅ 识别阻塞的源头

  • ✅ 看到具体的阻塞SQL语句

  • ✅ 在死锁发生前进行干预


💡 最佳实践建议

  1. 📝 生产环境务必配置日志log_lock_waits = on 是你的生命线

  2. ⏱️ 合理设置超时deadlock_timeout 保持默认1秒即可

  3. 🔍 定期检查日志:关注 pg_stat_database 中死锁计数器的变化

  4. 🛠️ 代码层面预防:确保事务中的SQL操作顺序一致

  5. 👀 实时监控:使用系统视图查询作为辅助诊断工具

预防胜于治疗!通过合理的应用设计和数据库配置,可以大大减少死锁的发生频率。🚀

http://www.dtcms.com/a/560697.html

相关文章:

  • 佛山响应式网站开发二级域名免费分发站
  • 【软考架构】案例分析-Web应用设计(应用服务器概念)
  • C++中的过滤器模式:原理、实现与应用
  • Kanass实践指南(4) - 测试团队如何通过kanass管理跟踪用例与缺陷
  • 天河做网站技术松江做网站费用
  • 面试Redis篇—————缓存穿透问题及解决策略
  • 【ComfyUI】通用 文生图转视频
  • 怎样建网站?西湖区住房和城市建设局网站
  • 教做宝宝衣服的网站济南网站优化多少钱
  • 分布式文件存储服务设计与实现优化
  • Qt-Nice-Frameless-Window: 一个跨平台无边框窗口(Frameless Window)解决方案
  • 跨平台游戏引擎 Axmol-2.9.1 发布
  • Redis性能优化避坑指南
  • 【Cache缓存】两路组相连和全相连
  • 青岛门头设计制作长春百度关键词优化
  • 青海网站制作的公司天津市网站建设公司
  • 数据结构04:链表的概念及实现单链表
  • springCloud二-SkyWalking3-性能剖析-⽇志上传-告警管理-接入飞书
  • 【项目基础】vue-class-component、vue-property-decorator、vuex-class、GeoJson
  • JWT 是由哪三个部分组成?如何使用JWT进行身份认证?
  • 【JUnit实战3_24】 第十四章:JUnit 5 扩展模型(Extension API)实战(下)
  • PostgreSQL pg_stat_bgwriter 视图各个字段详解
  • 简单的购物网站设计网页设计尺寸pc端
  • Unity 高效 ListView GridView
  • 【3DV 进阶-4】VecSet 论文+代码对照理解
  • Oracle实用参考(13)——Oracle for Linux (RAC)到Oracle for Linux(单实例)间OGG单向复制环境搭建(2)
  • 前端开发 网站建设头像logo图片在线制作免费
  • 电话语音接入扣子介绍
  • Go分布式追踪实战:从理论到OpenTelemetry集成|Go语言进阶(15)
  • Vue-理解 vuex