SELECT ... *FOR UPDATE* 的目的是啥?

Posted

技术标签:

【中文标题】SELECT ... *FOR UPDATE* 的目的是啥?【英文标题】:What's the purpose of SELECT ... *FOR UPDATE*?SELECT ... *FOR UPDATE* 的目的是什么? 【发布时间】:2011-07-21 15:29:56 【问题描述】:

我很困惑你为什么要指定FOR UPDATE——为什么数据库会关心你要如何处理来自SELECT的数据?

编辑:对不起,我问的问题很糟糕。我知道文档说它把事情变成了“锁定读取”——我想知道的是“在指定FOR UPDATE 和不指定它之间存在哪些可观察行为会有所不同的情况——也就是说,什么那个锁具体需要吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

是的——我阅读了文档——但这对 RDBMS 的用户有什么作用? 啊——所以这会让你做类似START TRANSACTION; SELECT MAX(id+1) AS newid FROM thetable FOR UPDATE; INSERT INTO thetable (id) VALUES (newid); COMMIT; 的事情——而且你知道MAX() + 1 返回的值不会与其他人冲突?【参考方案2】:

这旨在解决的特定情况是当您需要读取和更新列中的值时。有时您可以先更新列(锁定它)然后再读取它,例如:

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;

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

它会创建一个锁定读取,这样在你完成之前没有人可以更新它,例如

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”和分号之间有什么区别?) 跑人!语句以分号结束 我不明白 - 语句以分号终止 yes - 这意味着在上面的示例中 FOR UPDATE 不会影响 UPDATE 语句 - 因为它们是分开的用分号分隔的语句(因此我对为什么需要存在该指令感到困惑)。 当两个语句都运行完你就完成了..也许这样更清楚 事务结束时。 IE。犯罪。如果您启用了自动提交并且正在运行单个语句,那将毫无意义。【参考方案5】:

SELECT FOR UPDATE 告诉 RDBMS 您要锁定这些行,这样在您更新并提交或回滚并解锁它们之前,其他人无法访问它们:

http://www.techonthenet.com/oracle/cursors/for_update.php

【讨论】:

嗯?游标和这个有什么关系?

以上是关于SELECT ... *FOR UPDATE* 的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章

select * from salgrade for update和select * from salgrade for update nowait区别

select..for update

为啥不支持它的数据库可以简单地忽略 select_for_update?

既然没有事务 SELECT FOR UPDATE 是没有意义的,而且事务本身使用锁,那么 SELECT FOR UPDATE 的用例是啥?

显式锁select for update 用法

for update 和 for update nowait 的区别