PostgreSQL死鎖排查與解決指南
PostgreSQL 16默認(rèn)會記錄死鎖嗎?
答案是不會!
雖然PostgreSQL 16具備死鎖檢測機制(在等待鎖超過deadlock_timeout后會自動檢測并解決死鎖),但默認(rèn)不會將死鎖的詳細信息記錄到日志中。這就意味著你知道發(fā)生了死鎖,卻不知道具體原因!
如何配置死鎖日志記錄
1. 修改配置文件
找到PostgreSQL數(shù)據(jù)目錄下的postgresql.conf文件,添加以下配置:
# 記錄鎖等待信息(關(guān)鍵?。? log_lock_waits = on # 死鎖檢測超時時間(默認(rèn)1秒) deadlock_timeout = 1s # 日志級別至少設(shè)置為log log_min_messages = log # 詳細的日志前綴 log_line_prefix = '%t [%p]: db=%d,user=%u,app=%a,client=%h '
2. 重新加載配置
-- 在psql中執(zhí)行 SELECT pg_reload_conf();
或者使用命令行:
pg_ctl reload -D /path/to/your/data/directory
死鎖日志分析實例
配置完成后,當(dāng)死鎖發(fā)生時,你會在日志中看到類似這樣的詳細信息:
2025-11-02 10:23:41.123 CST [12345]: LOG: ?? Powered by Moshow 鄭鍇 | 更多技術(shù)干貨: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: 等待事務(wù) 123456 的 ShareLock; 被進程 12346 阻塞. 2025-11-02 10:23:41.123 CST [12345]: PROCESS 12345: 執(zhí)行語句: UPDATE accounts SET balance = balance - 100.00 WHERE user_id = 1; 2025-11-02 10:23:41.123 CST [12346]: PROCESS 12346: 等待事務(wù) 123457 的 ShareLock; 被進程 12345 阻塞. 2025-11-02 10:23:41.123 CST [12346]: PROCESS 12346: 執(zhí)行語句: 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
- 死鎖場景:兩個進程互相等待對方釋放鎖
- 執(zhí)行的SQL:兩個UPDATE語句在競爭相同的資源
- 解決方案:PostgreSQL選擇中止進程12345的事務(wù)
- 溫和終止(優(yōu)先嘗試): SELECT pg_terminate_backend(12345);
- 強制終止(若溫和方式失?。? SELECT pg_cancel_backend(12345);
實時監(jiān)控:系統(tǒng)視圖分析
除了查看日志,你還可以實時監(jiān)控當(dāng)前的鎖等待情況:
強大的鎖等待查詢語句
--?? Powered by Moshow 鄭鍇 | 更多技術(shù)干貨:https://zhengkai.blog.csdn.net
SELECT
blocked_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.locktype
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND 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;查詢結(jié)果示例:
| blocked_pid | blocked_user | blocking_pid | blocking_user | blocked_statement |
|---|---|---|---|---|
| 12345 | app_user | 12346 | app_user | UPDATE accounts SET balance = balance - 100 WHERE user_id = 1 |
| 12347 | web_user | 12348 | batch_user | DELETE FROM orders WHERE status = 'cancelled' |
這個查詢能幫你:
- 實時發(fā)現(xiàn)阻塞情況
- 識別阻塞的源頭
- 看到具體的阻塞SQL語句
- 在死鎖發(fā)生前進行干預(yù)
最佳實踐建議
- 生產(chǎn)環(huán)境務(wù)必配置日志:log_lock_waits = on 是你的生命線
- 合理設(shè)置超時:deadlock_timeout 保持默認(rèn)1秒即可
- 定期檢查日志:關(guān)注 pg_stat_database 中死鎖計數(shù)器的變化
- 代碼層面預(yù)防:確保事務(wù)中的SQL操作順序一致
- 實時監(jiān)控:使用系統(tǒng)視圖查詢作為輔助診斷工具
預(yù)防勝于治療!通過合理的應(yīng)用設(shè)計和數(shù)據(jù)庫配置,可以大大減少死鎖的發(fā)生頻率。
以上就是PostgreSQL死鎖排查與解決指南的詳細內(nèi)容,更多關(guān)于PostgreSQL死鎖排查的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vcenter清理/storage/archive空間的處理方式
通過SSH登陸到Vcenter并檢查/storage/archive目錄發(fā)現(xiàn)占用過高,該目錄用于存儲歸檔的日志文件和歷史數(shù)據(jù),解決方案是保留近30天的歸檔文件,這篇文章主要給大家介紹了關(guān)于Vcenter清理/storage/archive空間的處理方式,需要的朋友可以參考下2024-11-11
將PostgreSQL的數(shù)據(jù)實時同步到Doris的技巧分享
眾所周知,在兩個毫不相干的數(shù)據(jù)管理系統(tǒng)之間進行數(shù)據(jù)同步,特別是實時同步,其復(fù)雜程度足以讓高級DBA腦瓜疼,本文給大家介紹了將PostgreSQL的數(shù)據(jù)實時同步到Doris的技巧分享,需要的朋友可以參考下2024-03-03
postgreSQL數(shù)據(jù)庫默認(rèn)用戶postgres常用命令分享
這篇文章主要介紹了postgreSQL數(shù)據(jù)庫默認(rèn)用戶postgres常用命令分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
postgresql 切換 log、xlog日志的實現(xiàn)
這篇文章主要介紹了postgresql 切換 log、xlog日志的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
PostgreSQL 實現(xiàn)sql放入文件批量執(zhí)行
這篇文章主要介紹了PostgreSQL 實現(xiàn)sql放入文件批量執(zhí)行,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
PostgreSQL數(shù)據(jù)庫字符串拼接、大小寫轉(zhuǎn)換以及substring詳解
在日常工作中會遇到將多行的值拼接為一個值展現(xiàn),下面這篇文章主要給大家介紹了關(guān)于PostgreSQL數(shù)據(jù)庫字符串拼接、大小寫轉(zhuǎn)換以及substring的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04
解決sqoop從postgresql拉數(shù)據(jù),報錯TCP/IP連接的問題
這篇文章主要介紹了解決sqoop從postgresql拉數(shù)據(jù),報錯TCP/IP連接的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
PostgreSQL數(shù)據(jù)庫中窗口函數(shù)的語法與使用
這PostgreSQL中提供了窗口函數(shù),一個窗口函數(shù)在一系列與當(dāng)前行有某種關(guān)聯(lián)的表行上進行一種計算。下面這篇文章主要給大家介紹了關(guān)于PostgreSQL數(shù)據(jù)庫中窗口函數(shù)的語法與使用的相關(guān)資料,需要的朋友可以參考下2019-03-03

