我很困惑你为什么要指定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
FOR UPDATE
不会影响 UPDATE
语句——因为它们是由分号分隔的单独语句(这就是我为什么困惑指令需要存在的原因)。 - Billy ONeal它将锁定行(或整个表),以便在另一个会话中不能同时更新行。该锁定保持直到事务提交或回滚。
START TRANSACTION; SELECT MAX(id+1) AS newid FROM thetable FOR UPDATE; INSERT INTO thetable (id) VALUES (newid); COMMIT;
—— 你会知道MAX() + 1
返回的值不会与其他人冲突? - Billy ONeal