1. 程式人生 > 資料庫 >postgresql表死鎖問題的排查方式

postgresql表死鎖問題的排查方式

1.查詢啟用的執行中的sql,檢視有哪些更新update的sql。

select *
from pg_stat_activity
where state = 'active';

2. 查詢表中存在的鎖

select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname
from pg_locks a
join pg_class b on a.relation = b.oid
where lower(b.relname) = 'h5_game';

3. 殺掉死鎖程序

select pg_terminate_backend(pid)
from pg_stat_activity
where state = 'active'
and pid != pg_backend_pid()
--and pid = 14172
and pid in (select a.pid
from pg_locks a
join pg_class b on a.relation = b.oid
where lower(b.relname) = 'news_content')

鎖模式

/* NoLock is not a lock mode,but a flag value meaning "don't get a lock" */
#define NoLock                 0
 
#define AccessShareLock         1        /* SELECT */
#define RowShareLock          2        /* SELECT FOR UPDATE/FOR SHARE */
#define RowExclusiveLock        3        /* INSERT,UPDATE,DELETE */
#define ShareUpdateExclusiveLock 4       /* VACUUM (non-FULL),ANALYZE,CREATE
                                         * INDEX CONCURRENTLY */
#define ShareLock                5        /* CREATE INDEX (WITHOUT CONCURRENTLY) */
#define ShareRowExclusiveLock  6        /* like EXCLUSIVE MODE,but allows ROW
                                         * SHARE */
#define ExclusiveLock          7        /* blocks ROW SHARE/SELECT...FOR
                                         * UPDATE */
#define AccessExclusiveLock       8        /* ALTER TABLE,DROP TABLE,VACUUM
                                         * FULL,and unqualified LOCK TABLE */

補充:Postgresql死鎖的處理

背景:

對錶進行所有操作都卡住,原因可能是更新表時導致這個表死鎖了,開始進行排查

解決一:查詢pg_stat_activity有沒有記錄

pg版本10.2

select pid,query,* from pg_stat_activity where datname='死鎖的資料庫' and wait_event_type = 'Lock';
select pg_cancel_backend('死鎖那條資料的pid值');##只能殺死select 語句,對其他語句不生效
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是否有這個物件的鎖

select oid,relname from pg_class where relname='table name';
select locktype,pid,relation,mode,granted,* from pg_locks where relation= '上面查詢出來的oid';
select pg_terminate_backend('程序ID');

問題解決!!!

坑:一開始不知道pg_cancel_backend(‘死鎖那條資料的pid值');##只能殺死select 語句,對其他語句不生效,殺了程序查詢發現還存在,反覆殺反覆存在,換了pg_terminate_backend(‘程序ID')問題就解決了。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。