SELECT ... *FOR UPDATE*的目的是什么?

10

我很困惑你为什么要指定FOR UPDATE -- 数据库为什么关心你从SELECT中获取的数据要做什么?

编辑:抱歉,我表达不清楚。我知道文档上说它会将事物变成"锁定读取" -- 我想知道的是,在指定FOR UPDATE和不指定的情况下,观察到的行为有哪些不同的情况存在 -- 也就是说,那个锁具体包含了什么?

5个回答

20

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 是没有意义的。


是的 - 我阅读了文档 - 但这对于关系数据库管理系统的用户有什么作用呢? - Billy ONeal
2
啊——这样做可以让你像这样执行操作:START TRANSACTION; SELECT MAX(id+1) AS newid FROM thetable FOR UPDATE; INSERT INTO thetable (id) VALUES (newid); COMMIT; —— 你会知道 MAX() + 1 返回的值不会与其他人冲突? - Billy ONeal

3
这个设计的特定情况是当你需要读取和更新列中的值时。有时候你可以先更新列(锁定它),然后再读取它,例如:
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;

2

嗯?光标和这有什么关系? - Billy ONeal

0

什么?语句在分号处结束了!(“FOR UPDATE”和分号之间可以放什么?) - Billy ONeal
当它运行完毕,人类!该语句在分号处终止。 - SQLMenace
我不明白——语句在分号处终止,这意味着在你上面的例子中 FOR UPDATE 不会影响 UPDATE 语句——因为它们是由分号分隔的单独语句(这就是我为什么困惑指令需要存在的原因)。 - Billy ONeal
当这两个语句都执行完毕后,你就完成了。也许这能让它更清晰明了。 - SQLMenace
RDBMS如何知道呢?当连接关闭时吗? - Billy ONeal
4
当事务结束时,即COMMIT。如果您开启了自动提交并且仅运行单个语句,则此操作无意义。 - gtd

0

它将锁定行(或整个表),以便在另一个会话中不能同时更新行。该锁定保持直到事务提交或回滚。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接