2012-03-15 96 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,我们可能会遇到麻烦,因为在我们向它们写入新值之前可能会更新行,并且此更新可能会丢失。

相关问题