SELECT ... FOR UPDATE适用于一次性行方案吗?

时间:2012-03-15 11:47:36

标签: mysql locking

我有一个promo_codes表,可以通过Web应用程序激活。有一个state列,可以是0表示未激活,1表示激活。如果我用

运行交易
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?

1 个答案:

答案 0 :(得分:0)

SELECT for UPDATE和LOCK IN SHARE MODE修饰符有效地在READ-COMMITTED隔离模式下运行,即使当前隔离模式是REPEATABLE-READ。这是因为Innodb只能锁定当前版本的行。考虑类似的情况和行被删除。即使Innodb能够在不再存在的行上设置锁定 - 它对你有用吗?不是真的 - 例如,您可以尝试使用SELECT FOR UPDATE更新刚刚锁定的行但是此行已经消失,因此您会在更新您认为已成功锁定的行时遇到意外错误。无论如何,这样做是为了让所有其他决定更加麻烦。

LOCK IN SHARE MODE实际上通常用于绕过多版本化并确保我们正在读取大多数当前数据,并确保无法更改。例如,这可以用于读取行的集合,为其中一些行计算新值并将其写回。如果我们不使用LOCK IN SHARE MODE,我们可能会遇到麻烦,因为在我们向它们写入新值之前可以更新行,这样的更新可能会丢失。