postgresql 死鎖處理


緣起

遇到一個奇怪的現象,select和delete表時正常執行,但truncate和drop表時會一直運行,也不報錯。

原因

"drop table " 和 "truncate table " 需要申請排它鎖 "ACCESS EXCLUSIVE ", 執行這個命令卡住時,說明此時這張表上還有操作正在進行,比如查詢等,
那么只有等待這個查詢操作完成,"drop table" 或"truncate table"或者增加字段的SQL 才能獲取這張表上的 "ACCESS EXCLUSIVE" 鎖 ,操作才能進行下去。

1.檢索出死鎖進程的ID。

select oid,relname from pg_class where relname='all_data';

檢索出來的字段中,【wating 】字段,數據為t的那條,就是死鎖的進程。找到對應的【procpid 】列的值。

2.將進程殺掉。

SELECT pg_cancel_backend('死鎖那條數據的procpid值 ');

結果:運行完后,再次更新這個表,sql順利執行。

 

如果pg_stat_activity 沒有記錄,則查詢pg_locks是否有這個對象的鎖

 

select locktype,pid,relation,mode,granted,* from where relation= '上面查詢出來的oid';

殺掉進程

select pg_cancel_backend('進程ID');

另外pg_terminate_backend()函數也可以殺掉進程。

總結

select oid,relname from pg_class where relname='all_data';
select locktype,database,pid,relation ,mode from pg_locks where relation=上面oid;
select * from pg_stat_activity where pid = 上面pid
select pg_terminate_backend(上面pid);

刪除數據庫說被鏈接

異常

db_v43=> drop database test_db;
ERROR:  database "test_db" is being accessed by other users
DETAIL:  There is 1 other session using the database.

解決

SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='數據庫名' AND pid<>pg_backend_pid(); 

然后就可以刪除數據庫了

 

查看表結構依賴

在表結構修改(增刪改)利於排除死鎖

with t_wait as                     
(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a,
transactionid,b.query,b.xact_start,b.query_start,b.usename,b.datname 
  from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted),
t_run as 
(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,
a.classid,a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,
a,transactionid,b.query,b.xact_start,b.query_start,
b.usename,b.datname from pg_locks a,pg_stat_activity b where 
a.pid=b.pid and a.granted) 
select r.locktype,r.mode r_mode,r.usename r_user,r.datname r_db,
r.relation::regclass,r.pid r_pid,
r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start,
r.query_start r_query_start,
now()-r.query_start r_locktime,
r.query r_query,w.mode w_mode,
w.pid w_pid,w.page w_page,
w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start,
now()-w.query_start w_locktime,w.query w_query  
from t_wait w,t_run r where
  r.locktype is not distinct from w.locktype and
  r.database is not distinct from w.database and
  r.relation is not distinct from w.relation and
  r.page is not distinct from w.page and
  r.tuple is not distinct from w.tuple and
  r.classid is not distinct from w.classid and
  r.objid is not distinct from w.objid and
  r.objsubid is not distinct from w.objsubid and
  r.transactionid is not distinct from w.transactionid and
  r.pid <> w.pid
  order by 
  ((  case w.mode
    when 'INVALID' then 0
    when 'AccessShareLock' then 1
    when 'RowShareLock' then 2
    when 'RowExclusiveLock' then 3
    when 'ShareUpdateEx
clusiveLock' then 4
    when 'ShareLock' then 5
    when 'ShareRowExclusiveLock' then 6
    when 'ExclusiveLock' then 7
    when 'AccessExclusiveLock' then 8
    else 0
  end  ) + 
  (  case r.mode
    when 'INVALID' then 0
    when 'AccessShareLock' then 1
    when 'RowShareLock' then 2
    when 'RowExclusiveLock' then 3
    when 'ShareUpdateExclusiveLock' then 4
    when 'ShareLock' then 5
    when 'ShareRowExclusiveLock' then 6
    when 'ExclusiveLock' then 7
    when 'AccessExclusiveLock' then 8
    else 0
  end  )) desc,r.xact_start;
  
  
  select count(1) from pg_stat_activity where state !='idle';
  
  
  
  SELECT
  locktype,
pg_locks.pid, virtualtransaction, transactionid, nspname, relname, mode, granted, cast(date_trunc('second',query_start) AS timestamp) AS query_start, query AS query FROM pg_locks LEFT OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oid) LEFT OUTER JOIN pg_namespace ON (pg_namespace.oid = pg_class.relnamespace), pg_stat_activity WHERE NOT pg_locks.pid=pg_backend_pid() AND pg_locks.pid=pg_stat_activity.pid;  

批量刪除

把pid拷貝到del文件

cat del |sort | uniq | awk '{print "select pg_terminate_backend("$1");"}'

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM