Postgresql

deadlock_timeout 配置參數在 Postgresql 中檢測到什麼樣的死鎖?

  • June 29, 2018

我的總體目標是在40P01/ERRCODE_T_R_DEADLOCK_DETECTED檢測到死鎖時從 postgres 獲取一個。(更準確地說,我想在 Hibernate 中獲取 LockAcquisitionException,這是40P01/ERRCODE_T_R_DEADLOCK_DETECTED錯誤程式碼在PostgreSQL81Dialect.java中翻譯的異常)我使用 Postgresql 9.6。

為此,我認為我應該按照19.12deadlock_timeout的建議設置和log_lock_waits配置變數。鎖管理

deadlock_timeout(整數)這是在檢查是否存在死鎖條件之前等待鎖定的時間量,以毫秒為單位。

$$ … $$ 設置時log_lock_waits,此參數還確定在發出有關鎖定等待的日誌消息之前等待的時間長度。如果您正在嘗試調查鎖定延遲,您可能需要設置比正常更短的deadlock_timeout.

我在 postgresql.conf 中設置了以下值

log_lock_waits = on         # log lock waits >= deadlock_timeout
deadlock_timeout = 5s

現在,當我創建一個死鎖情況(從 Java 使用 Hibernate)時,我在 postgresql.log 中找到以下內容

LOG:  process 17493 still waiting for ShareLock on transaction 322815 after 5000.464 ms
DETAIL:  Process holding the lock: 17495. Wait queue: 17493.
CONTEXT:  while updating tuple (132,35) in relation "publication"

但是不會40P01/ERRCODE_T_R_DEADLOCK_DETECTED產生錯誤(並發送到 JDBC 驅動程序)。

我深入研究了 postgres 原始碼,發現通過設置完成的死鎖檢測deadlock_timeout/log_lock_waits與生成的機制不同40P01/ERRCODE_T_R_DEADLOCK_DETECTEDdeadlock_timeout案例在 backend/storage/lmgr/proc.c中處理 ,而案例40P01/ERRCODE_T_R_DEADLOCK_DETECTEDbackend/storage/lmgr/deadlock.c

所以,我的問題是:

  • 這實際上是檢測到的兩種不同類型的死鎖嗎?
  • deadlock_timeout當基於死鎖檢測發生時,有沒有辦法得到錯誤?
  • 實際上如何才能ERRCODE_T_R_DEADLOCK_DETECTED強制發生錯誤?

更新:我用來進入死鎖情況的程式碼是這樣的(Spring/Java):

// This is in a Transaction managed by spring
Publication p = em.find(Publication.class, id);
p.setComment("Outer "+new Date());
em.flush();

// This utility method runs the lambda expression in a new Transaction
// using Spring's TransactionTemplate and tries to update
// the same Publication that is about to be updated by the 
// "outer" transaction
Utils.runInSeparateTransaction(status -> {
   Publication p2 = em.find(p.getClass(), p.getMtid());
   p2.setComment("Inner "+new Date());
   return p2;
   // Would flush/commit after the return, but will "hang" instead.
   // Here I would expect the deadlock error but only get the
   // deadlock log.
};

// Outer transaction would commit at this point but will 

死鎖是指多個事務在它們交叉獲取的鎖中相互衝突的情況。如果不中止其中一項交易,就不可能解決這種情況。引擎中止這樣的事務並ERRCODE_T_R_DEADLOCK_DETECTED出現錯誤。

log_lock_waits主要與死鎖無關,它旨在提醒某些查詢卡在等待鎖定的情況,這意味著其他事務保持鎖定的時間過長。

這實際上是檢測到的兩種不同類型的死鎖嗎?

不,您似乎在這裡混淆了鎖和死鎖。

當基於 deadlock_timeout 的死鎖檢測發生時,有沒有辦法得到錯誤?

它是自動的。如果沒有出現該錯誤,那是因為沒有死鎖。

實際上如何強制發生 ERRCODE_T_R_DEADLOCK_DETECTED 錯誤?

通過創建一個至少有兩個事務衝突的實際死鎖。有關簡單範例,請參見postgres deadlock without explicit lock on SO。

引用自:https://dba.stackexchange.com/questions/195477