0

我最近遇到了postgres併發bug,我不會在這裏重複。最初的帖子可以在this link找到。postgres 9.5行級別鎖併發異常

我仍然試圖更好地理解postgres如何處理可序列化的併發性。我的情況是這樣的。我有一個存儲過程讀取一個表,然後根據讀取的輸出插入。此存儲過程(如果由多個客戶端調用)會導致40001讀取/寫入依賴項異常。

問題是這樣的。讓我們假設存儲過程讀取一個表,然後根據讀取插入它,只讀取一些行。如果確保每次調用存儲過程進行讀插入操作都會觸及不同的行,那麼併發異常是否會消失? postgres是否足夠聰明以跟蹤在事務期間讀取哪些行,以便它可以準確地檢測由異常導致的異常對這些特定行的修改?如果是的話,這個機制有多可靠?它可以在某些情況下和postgres進行優化,只是爲了安全拋出任何讀取表的修改異常?

+1

你爲什麼不把你的發現發送到postgres郵件列表?這就是您可以找到真正的專家和首先編寫代碼的人員的地方。 https://www.postgresql.org/list/ –

+0

*「我有一個存儲過程讀取表,然後根據讀取的輸出插入。」*是否「讀取表」以確定行或行存在?它讀了多少表格? –

+0

不需要。實際上,跨越3個表的讀取需要中間關節/計數。這不是一個簡單的情況,檢查一行是否存在,如果不存在,則插入。這可以通過'insert'的on衝突條款來處理。 讀取本身有一個涉及'WHERE'子句,它會自動限制讀取的行數。 – cplusplusrat

回答

0

首先,您在鏈接中遇到的問題是而不是的一個錯誤,但意圖和記錄的行爲。

我收集你正在使用事務隔離級別SERIALIZABLE

在這種模式下,您讀取的每一行都被鎖定了一個特殊的SIReadLock,它不會阻塞任何東西,而是用來確定是否發生序列化異常,在這種情況下事務被串行化錯誤中斷。

請注意,不僅是以這種方式鎖定返回給您的行,還會鎖定在執行查詢期間訪問的所有表中的所有行。因此,如果您的執行計劃中存在順序掃描,則表中的所有行都將有SIReadLock。而且,如果表上的這些鎖太多,則會升級到頁或表級鎖。

所以有可能不必要地鎖定行。除此之外,用於檢測不一致性的算法可以報告誤報(這在計算上會太精確)。

因此,您可能會在您描述的情況下接收到序列化錯誤,但只要一切都保持簡單並且沒有順序掃描,就不會期待任何錯誤。

序列化錯誤是正常的,預計在SERIALIZABLE隔離級別。您的應用程序必須準備好通過重試事務來處理它們。這是您不必擔心數據一致性而必須付出的代價。