Postgresql
Postgres 40001 異常條件插入
我有 3 張桌子
A
,B
和C
。actOnABC(i)
一個對錶進行只讀操作的函式:IF actOnABC(i) = 0 THEN RAISE EXCEPTION 'Message'; ELSE INSERT INTO TABLE B VALUES(...); END IF;
我使用 Spring JDBC 執行它,事務隔離級別設置為 SERIALIZABLE。
隨著並發事務的負載/數量增加,我收到帶有消息的異常:
錯誤:由於事務之間的讀/寫依賴關係,無法序列化訪問。
可以說,我有兩個並發的 Transactions
T1
和T2
.T1 and T2
兩者都試圖插入。如果說,T1
成功地將插入先插入到 table 中B
,那麼可能actOnABC(i)
已經評估過的結果T2
可能會改變。因此T2
會拋出異常。我對情況的理解正確嗎?另外,有什麼方法可以將
actOnABC(i)
呼叫與INSERT
語句結合起來以避免這種競爭條件?我確實考慮過使用事務級鎖。但恐怕這行不通,因為我有其他儲存過程正在積極更新表A
,B
並且C
.有沒有更聰明的方法來處理這種情況?
編輯:有關儲存過程的更多資訊
actOnABC()
。此過程返回一個整數,其計算如下。SELECT count(*) into tmp_a from (... access tables..); SELECT count(*) into tmp_b from (... access tables...); return tmp_a - tmp_b;
請參閱PostgreSQL 文件,第 13 章。並發控制,13.2。可重複讀取和可序列化隔離級別描述的事務隔離:
由於序列化失敗,使用此級別的應用程序必須準備好重試事務。
在 Postgres 函式中是不可能的——客戶端應用程序需要重試。在 Serializable 隔離級別中,即使是只讀事務也需要重試。
你應該可以把它放到一個
INSERT INTO .. SELECT
INSERT INTO b (a,b,c) SELECT a,b,c FROM ( VALUES (...) ) AS t(a,b,c) WHERE actOnABC(i) = 0;