2017-09-06 78 views
0

據我所知,PostgreSQL使用MVCC來處理並行事務,但我不知道在以下情況下會發生什麼:Postgresql事務「COMMIT」線程安全嗎?

Client1      Client2      Time 
------------------------------------------------------------------- 
BEGIN       BEGIN      time=t0 
Update row where id=1 Update row where id=1    time=t1 
COMMIT      COMMIT      time=t2 

無論是客戶端將在時間啓動事務= T0,更新同一行ID爲= 1,並且將在時間= t2提交事務。由於提交是在同一時間完成的(時間= t2),它們將被並行執行還是由PostgreSQL按順序執行?如果它們並行運行,是否有數據損壞的可能性?謝謝。

編輯:「COMMIT」與libPQ一起使用。在psql中,COMMIT = END。

+1

這兩個更新不可能同時發生**。第二個更新將等到第一個提交(或回滾) –

+0

謝謝。我對併發事務的很多場景感到困惑。非常感謝你糾正我。我從你的評論中得到了答案。 – Saurabh

回答

1

這篇文章充滿了誤解。

還有這裏沒有涉及線程,所以它根本不是「線程安全」的。 PostgreSQL使用多個進程,每個連接一個進程。客戶端應用程序可能不會共享線程之間的單個連接,除非它們確保它們執行適當的鎖定以一次停止使用它的多個線程。

你問的是關於併發性,而不是線程。而你並沒有真正詢問「線程安全性」,而是關於原子性和隔離性。 See the PostgreSQL documentation chapter on concurrency control

在這種情況下:

  • 快照取自訪問該數據庫的第一條語句,所以他們在時間t1(更新)採取非T2(提交)。在這種情況下,兩個UPDATE都會影響同一行。他們會鎖定這一行,然後等到另一個提交或回滾。那時候,等待中的人會重新檢查它的WHERE條款是否仍然匹配,然後它會繼續進行自己的更改。
  • 明確的COMMITBEGIN這裏是噪聲,它們並不重要,因爲如果您單獨運行語句,它們會自動包裝在單個語句事務中。

所以

由於提交的在同一時刻(時間= T2)

他們不能在完全相同的時間內完成,因爲他們採取簡單的鎖更新完成一些共享內存數據結構並寫入事務日誌。但他們確實重疊。從邏輯上講,一個仍然在另一個之前提交。

您似乎認爲只有在您提交時纔會生效。這不是真的。語句立即運行,所以這些UPDATE在您發送它們後立即運行。其他交易只有纔會變爲可見,直到提交。

如果它們並行運行,是否有數據損壞的可能性?

不,這就是PostgreSQL和其他RDBMS的全部意義。不會有數據損壞

在這種情況下,兩個UPDATE將通過使用行鎖定將它們自行排序。如果你在這裏嘗試了你在做什麼,在兩個併發會話中,但是不要提交它們,然後查詢pg_locks,你會看到一個正在等待另一個。

結果可能與如果您連續運行兩個事務而不是同時運行會發生什麼不同。我們將在PostgreSQL文檔的事務隔離章節中詳細討論這個問題,並舉例說明。

交易不是神祕的祕密醬,讓你忽略併發問題。如果您使用SERIALIZABLE事務,則它們距離它不太遠,但是您的應用必須準備好重試任何事務,因爲它們可能由於序列化失敗而隨時失敗。 (無論如何,編寫良好的應用程序可以做到這一點,因爲即使是READ COMMITTED xacts也可能因死鎖等原因而失敗)。