【问题标题】:Block MySQL reads while updating更新时阻止 MySQL 读取
【发布时间】:2017-10-01 03:07:23
【问题描述】:

我有两个简单的查询,一个是读取,一个是更新表。如何在更新运行时锁定选择查询的读取。现在在 MySQL InnoDB 中,我注意到写入/更新默认情况下是锁定的,但读取/选择在事务之前获取旧数据。

我尝试在更新查询中使用事务然后SELECT ... FOR UPDATE - 在事务之外 - 但它似乎没有解决问题。另外,出于测试目的,我想知道如何减慢 UPDATE 查询的速度。我遇到了 SLEEP(X),但我不知道如何在更新查询中实现它。

如何让每个查询等待读取/写入,直到写入完成。

【问题讨论】:

    标签: mysql select sql-update


    【解决方案1】:

    使用READ-COMMITTED 事务将查看最新提交的。更改,并且使用 SELECT ... LOCK IN SHARE MODE 将阻止读取,直到提交任何未完成的更新。

    试试这个。在一个屏幕中,启动事务和更新。不需要 SLEEP(),只是不要提交事务。 UPDATE 创建的锁将继续存在,直到您提交为止。

    BEGIN;
    UPDATE MyTable SET something = '1234' WHERE id = 3;
    

    暂时不要提交。

    同时,在第二个屏幕中,将您的事务隔离设置为已提交的事务。无需启动显式事务,因为 InnoDB 查询使用事务,即使它是自动提交的。

    SET tx_isolation='READ-COMMITTED';
    
    SELECT * FROM MyTable WHERE id = 3 LOCK IN SHARE MODE;
    <hangs>
    

    LOCK IN SHARE MODE 让它等待,因为 UPDATE 创建了一个未完成的独占锁。

    在第一个屏幕中:

    COMMIT;
    

    在第二个屏幕中,瞧!阻塞读取被解除阻塞,您可以立即看到 UDPATE 的结果,而无需刷新您的事务。

    【讨论】:

    • 确实,我测试了它并且它有效,如果你不介意,你能迅速解释一两件事吗?首先为什么SELECT ... FOR UPDATE 不起作用?其次,我尝试不使用SET tx_isolation='READ-COMMITTED';,但它仍然有效。最后,提交是否使它只能在完成之前写入(默认情况下不是这样)。我知道其中一些可以通过谷歌搜索来回答,但我这样做了,如果你不介意花点时间的话,我想把它们清理一下。
    • SELECT ... FOR UPDATE 应该是一样的,我猜你以不同的顺序执行了这些步骤。我不知道。
    • 如果你使用自动提交,读提交模式的行为就像可重复读一样,因为每个语句都会启动一个新事务。但是,如果您将 SELECT 作为较长事务的一部分,您将需要使用已提交的读取。
    • COMMIT 释放 UPDATE 持有的锁。只要交易持续,锁就会被持有。
    • 谢谢,这很有帮助:)
    猜你喜欢
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多