Postgresql

Postgres 9.5死鎖,一個表上有很多更新+另一個表上有很多“選擇更新”

  • December 17, 2020

我有兩張桌子:“機器”和“魔法工具”。“magictools”指的是帶有外鍵的“機器”。

在執行其中許多請求時,我遇到了死鎖問題:

//this will produce an "AccessExclusiveLock" of type "tuple" on machines
SELECT FROM * machines FOR UPDATE where id = :id;
//this will produce a "RowExclusiveLock" on magictools and a "RowShareLock" on machines
UPDATE magictools SET collections = "large-json" where id = :id

據我了解,執行其中許多請求會產生死鎖。也許只是執行此操作的更新,我不知道。在這種情況下我應該如何避免死鎖?

我在這些表上有很多索引,也許我有太多索引?

以下是問題發生時 pg_activity 的報告。我不明白不同的模式和鎖類型,只是,這裡發生了什麼?是否有可能只是沒有任何事務的更新導致死鎖?

死鎖跟踪連結

沒有確定性ORDER BY

SELECT FROM * machines FOR UPDATE;

因此,多個事務可能會嘗試以不同(任意)順序和互鎖來獲取行鎖。

另外,為什麼要鎖定整個表machines以進行單個更新magictools?如果它確實是每個事務的單個UPDATEmagictools則根本不需要machines手動鎖定行。只需放下命令。(如果有多個,那麼你的問題是缺乏的。)

如果有充分的理由將許多或所有行鎖定在 中machines,請以確定的順序執行,例如:

SELECT FROM * machines ORDER BY id FOR UPDATE;

或者鎖定整個表,這也更便宜:

LOCK TABLE machines IN SHARE MODE;

SHARE MODE對於您擁有的 FK 案例來說已經足夠了。手冊中甚至有一個例子也暗示了這一點。

INSERT當然,與範例中的行級鎖不同,鎖定表也不允許。

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