2014-02-20 28 views
3

我有一個關於在線交易的問題,並希望通過SELECTUPDATE查詢澄清以下問題。SQL事務和表SELECT LOCK澄清

我會用下面的例子來向你解釋這個。

X正在進行在線交易。他的賬戶餘額是$1000。他將購買200美元的商品,之後他的賬戶餘額應該是$800。沒事兒;現在讓我解釋這個進一步

Begin DB transaction. 

Step 1: account balance is $1000 

{Select the balance from a different script} 

Step 2: Buy something for $200 

{Select the balance from another script} 

Step 3: Remaining balance $800 

Commit DB transaction 

正如你可以在步驟1和3的平衡已經被不同的查詢檢查事務外,另一個腳本執行步驟2和3

內再次檢查平衡之間見
  1. 使用默認的Mysql交易,第一個 和第二個餘額結果的值是多少?另外默認情況下,Mysql使用「SELECT ... LOCK IN SHARE MODE」 or 「SELECT ... FOR UPDATE」功能或者做 我們必須在我們的查詢中使用它們。
  2. 如果我們需要通過 上述返回800 $兩個平衡檢查查詢等待提交事務,我們可以使用的方法如: 「SELECT ... LOCK IN SHARE MODE」 or 「SELECT ... FOR UPDATE

  3. 而且你知道如果MySQL和郵政greSql手柄 交易與上面提到的不同嗎?

回答

3

在兩種MySQL的(與InnoDB的)和PostgreSQL,使用COMMITTED READ或SERIALIZABLE隔離模式下,平衡將是在步驟2和步驟3相同的變化將僅可見事務提交之後。

MySQL與MyISAM可能會有所不同,但如果您關心數據的正確性或一致性,則不應使用它。

除非您明確要求,否則MySQL和PostgreSQL都不會執行FOR SHAREFOR UPDATE

在READ COMMITTED模式下,PostgreSQL和MySQL(InnoDB)的行爲應該是相似的。有關PostgreSQL行爲的詳細信息,請參閱manual on transaction isolation

如果你想獲得800兩種讀取,如上所述,有兩件事情你必須做:

  • 作出更新的事務必須SELECT ... FOR UPDATE用戶的餘額記錄之前INSERT荷蘭國際集團的交易記錄餘額爲UPDATE;和

  • 閱讀交易(「其他腳本」)每當它讀取它時都必須有SELECT ... FOR SHARE餘額,所以它會在別人更新時等待,而不是隻讀取未更改的版本。

+0

嗨克雷格,謝謝你的細節 - 我有一個問題,雖然。如果「其他腳本」只是做了一個SELECT呢?在一個Web應用程序中,我們可能有許多腳本選擇數據,但可能有一個主腳本按照您所描述的執行SELECT FOR UPDATE。如果「其他腳本」只是執行一個SELECT,它會等待更新事務完成,還是隻是讀取它需要的值? (例如在上面的例子中爲1000美元)。如果它讀取$ 1000,那麼UPDATE腳本如何「鎖定」表來停止這個表? (在你有許多其他腳本讀取數據的情況下)。 – rishijd

+0

僅供參考,我瞭解「其他腳本」必須執行SELECT FOR SHARE才能獲取正確的數據。但是我的問題是,當你將一個新的SELECT FOR UPDATE引入到一個已經有許多其他「閱讀」腳本做一個SELECT(而不是SELECT FOR SHARE)的Web應用程序中。識別和更新所有其他「閱讀」腳本以使用SELECT FOR SHARE是唯一的答案嗎? – rishijd

+0

@rishijd如果您無法修復閱讀應用程序,則必須在開始更新之前先鎖定TABLE ... IN ACCESS EXCLUSIVE MODE。這可以防止其他任何事物讀取或寫入表格。 –