2015-09-06 65 views
0

我必須爲使用Postgres for database的非常高流量的Web應用程序編寫SQL事務。控制併發讀取然後更新然後在Postgres中寫入事務

我的問題是如何控制READ THEN UPDATE THEN WRITE事務的併發性,如果兩個用戶同時進行該事務?

對於高流量的Web應用程序,最佳做法是什麼?任何幫助/建議將非常感激。

在此先感謝。

+0

https://wiki.postgresql.org/wiki/Performance_Optimization –

+0

你能更具體的瞭解,究竟是什麼,您可以通過「讀,然後更新,然後寫上」是什麼意思?你的意思是通過應用程序進行讀 - 修改 - 寫嗎? –

+0

嗨克雷格,是我的意思是通過應用程序中的讀 - 修改 - 寫。 – John

回答

4

解釋性說明:我假設您的意思是read-modify-write工作負載,並且「READ THEN UPDATE THEN WRITE」的大寫字母並不意味着表示某些特殊事務選項SQL語法來自我不熟悉的產品。

如果你的web應用正在做讀 - 修改 - 寫高併發和流量的循環,那麼你就不能使用傳統的行鎖定:

  • BEGIN
  • SELECT primarykey, col1 FROM thetable WHERE ... FOR UPDATE
  • 過程中的應用
  • UPDATE blah SET col1 ... WHERE primarykey ...
  • COMMIT

因爲用戶「思考時間」和網絡延遲可能是無限的。大多數連接將在「應用程序中的過程」階段中停留無限期。每個等待會話意味着一個開放的空閒事務,這意味着有限的數據庫資源,如連接限制和內存消耗。

傳統的,完善的解決方案是使用optimistic concurrency control,有時誤導性地稱爲樂觀鎖定。一些ORM在本地支持。如果您直接使用SQL或通過不支持的框架,那麼實現它就很容易。其原理是,你的邏輯流程大致如下:

  • BEGIN READ ONLY TRANSACTION
  • SELECT primarykey, col1, row_version FROM thetable WHERE ...
  • COMMIT
  • 過程中的應用,並等待用戶響應
  • BEGIN
  • UPDATE blah SET col1 ..., row_version = row_version + 1 WHERE primarykey ... AND row_version = 'prev_row_version'
  • 檢查是否有UPDATE使用影響由數據庫中UPDATE響應
    • 返回如果它影響了零行受影響的行數的任何行,則WHERE條款不相符,暗示別人更新的行,因爲我們SELECT編它。回到開始並重新開始。
    • 如果它影響到一行,我們知道沒有人打我們來更新這一行,所以COMMIT並告訴用戶一切正常。

框架如Hibernate通過註釋列作爲行版本的自動支持這一點。

樂觀併發控制可以與傳統的鎖定和適當的數據庫觸發器進行互操作。參見例如the sample trigger I wrote for Hibernate inter-operation

相關問題