PostgreSQL死鎖相關
記得原來一老大哥說他運維ORACLE,發現死鎖的時候,總想著緩一緩,再拖一拖,沒準再檢視的時候。死鎖就已經自己釋放掉,不需要處理了(運維的無奈)。而在PostgreSQL中,事務可以按照任意順序加鎖。且PostgreSQL也有著其死鎖處理機制。
當程式請求加鎖的時候,如果失敗,會進入等待佇列。如果在佇列中已經存在一些程式要求本程式中已經持有的鎖,那麼為了儘量避免死鎖,可以把本程式插入到它們的前面。當一個鎖被釋放時,將會試圖喚醒等待佇列裡的程式。這個行為預防了死鎖的產生。
但是這種方法不能完全避免死鎖的產生,PostgreSQL提供如下圖的死鎖檢驗機制
且PostgreSQL使用等待圖(WFG)來檢驗死鎖,WFG為一個有向圖,頂點ABC表示申請加鎖的程式,XY有向邊表示依賴關係。
圖中的虛線為soft edge,實線為hard edge
當程式A和程式B都在某個鎖的等待佇列,且程式A在程式B的後邊,兩個程式的加鎖要求衝突,程式A在等待程式B,則存在從A到B的有向邊,名為soft edge;如果程式A的加鎖要求和程式B已經持有的鎖衝突,這時候從A指向B的為hard edge。
系統出現死鎖當且僅當WFG出現環,如果WFG中有soft edge環,則可以透過拓撲排序對佇列進行重排,嘗試消除死鎖。從頂點開始,沿著WFG有向邊走,如果能回到頂點,說明出現死鎖。如果路徑沒有出現soft edge,則直接終止此事務。如果存在soft edge,則記錄所有的soft edge,並嘗試對這個集合進行調整。
透過拓撲排序找到可行的方案,則採用此方案,消除死鎖,(不一定是最優的),否則死鎖清除失敗,終止該事務。
以下為pg12.1有向邊的資料結構
/* * One edge in the waits-for graph. * * waiter and blocker may or may not be members of a lock group, but if either * is, it will be the leader rather than any other member of the lock group. * The group leaders act as representatives of the whole group even though * those particular processes need not be waiting at all. There will be at * least one member of the waiter's lock group on the wait queue for the given * lock, maybe more. */ typedef struct { PGPROC *waiter; /* the leader of the waiting lock group */ PGPROC *blocker; /* the leader of the group it is waiting for */ LOCK *lock; /* the lock being waited for */ int pred; /* workspace for TopoSort */ int link; /* workspace for TopoSort */ } EDGE;
PostgreSQL對程式的檢驗過程為:
1.遞迴試圖檢驗和消除死鎖
2.測試當前佇列狀態是否會發生死鎖,如果不滿足約束性檢查,則死鎖。對soft edge調整,並檢驗是否合法。
3.判斷是否出現環,如果存在且不能調整,則死鎖。
相關引數:
1.Postgresql中,有一個死鎖等待事件的引數,預設是1s,也就是是說Postgresql後臺程式會以1s的頻率來檢測是否存在死鎖。
鎖等待超時
2.Postgresql中同樣可以設定鎖等待的超時時間,意味著當前事務在請求一個鎖的時候,一旦等待時長超出指定的時間,當前語句被中止。該引數的預設值為0,意味著發生鎖等待的時候永遠不超時,一直等待下去。預設情況下,鎖超時之後,當前Session的任何語句都會被回滾,即便是執行一個commit。
以下為標準鎖的鎖模式以及對應的操作
鎖手動處理:
1.查詢阻塞:
postgres=# SELECT w.query as waiting_query, postgres-# w.pid as w_pid, postgres-# w.usename as w_user, postgres-# l.query as locking_query, postgres-# l.pid as l_pid, postgres-# l.usename as l_user, postgres-# t.schemaname || '.' || t.relname as tablename postgres-# from pg_stat_activity w join pg_locks l1 on w.pid = l1.pid postgres-# and not l1.granted join pg_locks l2 on l1.relation = l2.relation postgres-# and l2.granted join pg_stat_activity l on l2.pid = l.pid join pg_stat_user_tables t on l1.relation = t.relid; waiting_query | w_pid | w_user | locking_query | l_pid | l_user | tablename --------------------+-------+----------+--------------------------------------+-------+----------+---------------- truncate tab_ysl ; | 5391 | postgres | update tab_ysl set id =9 where id=1; | 5524 | postgres | public.tab_ysl (1 row) //其中l_pid為阻塞者的pid,w_pid為被阻塞者的pid。
2.查詢表持有的鎖:
postgres=# select oid from pg_class where relname= 'tab_ysl'; oid ------ 24580 (1 row) 使pg_class.oid=pg_locks.relation,則表tab_ysl上持有的鎖為,RowExclusiveLock和 AccessExclusiveLock ,對應了update和truncate的操作。 postgres=# select * from pg_locks where pid in ('5524','5391'); locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath ---------------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+------+---------------------+---------+---------- relation | 13593 | 2659 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 2658 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 1249 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 3455 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 2663 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 2662 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 2685 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 2684 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 2615 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t relation | 13593 | 1259 | | | | | | | | 7/11 | 5524 | AccessShareLock | t | t virtualxid | | | | | 7/11 | | | | | 7/11 | 5524 | ExclusiveLock | t | t virtualxid | | | | | 6/181 | | | | | 6/181 | 5391 | ExclusiveLock | t | t transactionid | | | | | | 512 | | | | 7/11 | 5524 | ExclusiveLock | t | f relation | 13593 | 24580 | | | | | | | | 7/11 | 5524 | RowExclusiveLock | t | f transactionid | | | | | | 513 | | | | 6/181 | 5391 | ExclusiveLock | t | f relation | 13593 | 24580 | | | | | | | | 6/181 | 5391 | AccessExclusiveLock | f | f (16 rows)
殺掉阻塞者的程式,釋放鎖:
select pg_cancel_backend('上面查詢到的阻塞著的pid');
##注意##pg_cancel_backend(‘阻塞者的pid值’);只能殺死select語句, 對其他語句不生效,殺了之後查詢發現還存在,考慮使用pg_terminate_backend(‘程式ID’);
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69990629/viewspace-2789053/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PostgreSQL 死鎖異常SQL
- PostgreSQL 跟蹤checkpointer出現死鎖SQL
- MySQL鎖相關MySql
- PostgreSQL copy相關選項SQL
- PostgreSQL AutoVacuum 相關引數SQL
- mysql死鎖deadlock相關幾個系統變數innodb_lock_wait_timeoutMySql變數AI
- Lock鎖相關以及AQSAQS
- 死鎖
- 什麼是死鎖?如何解決死鎖?
- PostgreSQL模擬兩個update語句死鎖-利用掃描方法SQL
- 面試官:什麼是死鎖?怎麼排查死鎖?怎麼避免死鎖?面試
- 死鎖概述
- 作業系統(5) 死鎖的概念 死鎖產生的必要條件 死鎖的處理策略 預防死鎖 避免死鎖 死鎖的檢測和解除 銀行家演算法作業系統演算法
- PostgreSQL:鎖SQL
- 檢視oracle死鎖程式並結束死鎖Oracle
- 例項詳解 Java 死鎖與破解死鎖Java
- SpringBoot(一)啟動相關【死磕原始碼】Spring Boot原始碼
- 死鎖和可重入鎖
- MySQL 死鎖和鎖等待MySql
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- 【PG管理】postgresql資料庫管理相關SQL資料庫
- oracle鎖級別相關測試Oracle
- SQL SERVER死鎖查詢,死鎖分析,解鎖,查詢佔用SQLServer
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- 死鎖是什麼?如何預防和避免死鎖?
- golang中關於死鎖的思考與學習Golang
- GCD 死鎖原因GC
- 死鎖案例二
- 死鎖案例三
- 併發:死鎖
- 遭遇ITL死鎖
- 死鎖-舉例
- 死鎖案例分析
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- PostgreSQL並行查詢相關配置引數SQL並行
- MySQL中鎖的相關問題DTQUMySql
- 如何避免死鎖和活鎖? - simar
- SQLServer的死鎖分析(1):頁鎖SQLServer