2012-03-15 25 views
0

我有一張promo_codes的表格,可以通過網絡應用程序來激活。有一個state列,可以是0表示未激活或1表示激活。如果我運行SELECT ... FOR UPDATE適合一次性使用的行場景嗎?

SELECT FROM promo_codes WHERE state=0 LIMIT 1 FOR UPDATE; 
UPDATE promo_codes SET state=1 WHERE id = ?; 

發生第二個事務運行的事務:

SELECT FROM promo_codes WHERE state=0 LIMIT 1 FOR UPDATE; 

是否只是返回下一行,或者它阻止,直到第一個事務完成?

我已經開始考慮基於redis中的行ID來設置鎖,因爲它對我來說很明顯如何工作,我知道它不會在MySQL中創建任何性能問題,但另一方面,必須有一種乾淨而高效的方式來純粹用SQL來完成這項工作。也許我可以先使用UPDATE ... LIMIT 1,但是如何在這種情況下獲得促銷代碼的ID?

回答

0

即使當前隔離模式爲REPEATABLE-READ,SELECT for UPDATE和LOCK IN SHARE MODE修飾符也會有效地以READ-COMMITTED隔離模式運行。這是因爲Innodb只能鎖定當前版本的行。想想類似的情況和行被刪除。即使Innodb可以鎖定不再存在的行 - 它會對你有好處嗎?並非如此 - 例如,您可以嘗試更新剛剛使用SELECT FOR UPDATE鎖定的行,但此行已經消失,因此您會在更新您認爲已成功鎖定的行時發生意外錯誤。無論如何,這樣做是爲了做好所有其他決定會更麻煩。

LOCK IN SHARE MODE實際上常用於繞過多版本,並確保我們正在讀取大多數當前數據,並確保它不能被更改。例如,這可以用於讀取一組行,爲其中一些計算新值並將其寫回。如果我們不使用LOCK IN SHARE MODE,我們可能會遇到麻煩,因爲在我們向它們寫入新值之前可能會更新行,並且此更新可能會丟失。