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

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

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

【问题讨论】:

    标签: mysql 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

        【讨论】:

        • 嗯?游标和这个有什么关系?
        猜你喜欢
        • 2015-03-08
        • 1970-01-01
        • 1970-01-01
        • 2011-06-28
        • 2020-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多