我对你为什么要指定感到困惑FOR UPDATE
——为什么数据库关心你要如何处理来自SELECT
?
编辑:对不起,我问得不好。我知道文档说它把事情变成了“锁定读取”——我想知道的是“存在哪些情况下可观察的行为在指定FOR UPDATE
和不指定之间会有所不同——也就是说,具体是做什么的锁需要?
我对你为什么要指定感到困惑FOR UPDATE
——为什么数据库关心你要如何处理来自SELECT
?
编辑:对不起,我问得不好。我知道文档说它把事情变成了“锁定读取”——我想知道的是“存在哪些情况下可观察的行为在指定FOR UPDATE
和不指定之间会有所不同——也就是说,具体是做什么的锁需要?
http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
它与在事务中锁定表有关。假设您有以下内容:
START TRANSACTION;
SELECT .. FOR UPDATE;
UPDATE .... ;
COMMIT;
在 SELECT 语句运行后,如果您有另一个来自不同用户的 SELECT,它不会运行,直到您的第一个事务到达 COMMIT 行。
还要注意,FOR UPDATE
在事务之外是没有意义的。
这旨在解决的特定情况是当您需要读取和更新列中的值时。有时您可以先更新列(锁定它)然后再读取它,例如:
UPDATE child_codes SET counter_field = counter_field + 1;
SELECT counter_field FROM child_codes;
这将返回 counter_field 的新值,但这在您的应用程序中可能是可以接受的。如果您尝试重置该字段(因此您需要原始值),或者您有一个无法在更新语句中表达的复杂计算,那么这是不可接受的。在这种情况下,为了避免两个连接竞相更新同一列,您需要锁定该行。
如果您的 RDBMS 不支持 FOR UPDATE 那么您可以通过执行无用的更新来模拟它,例如
UPDATE child_codes SET counter_field = counter_field;
SELECT counter_field FROM child_codes;
UPDATE child_codes SET counter_field = 0;
SELECT FOR UPDATE 告诉 RDBMS 您要锁定这些行,以便在您更新并提交或回滚并解锁它们之前,其他人无法访问它们:
它创建一个锁定读取,这样在你完成之前没有人可以更新它,例如
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
见这里http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
它将锁定行(或整个表),以便行不能在另一个会话中同时更新。锁定一直保持到事务提交或回滚为止。