更新时阻止 MySQL 读取

Block MySQL reads while updating

提问人:John James 提问时间:10/1/2017 更新时间:10/1/2017 访问量:3883

问:

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

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

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

mysql 选择 sql-update

评论


答:

3赞 Bill Karwin 10/1/2017 #1

使用事务将查看最新提交的事务。更改和 using 将创建读取块,直到提交任何未完成的更新。READ-COMMITTEDSELECT ... LOCK IN SHARE MODE

试试这个。在一个屏幕中,启动交易和 UPDATE。不需要 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 的结果,而无需刷新事务。

评论

0赞 John James 10/1/2017
确实,我测试了它,它有效,如果你不介意的话,你能迅速解释一下我一两件事吗?首先,为什么不起作用?其次,我尝试了没有,它仍然有效。最后,提交是否使它无法只写入直到完成(虽然不是默认的)。我知道其中一些可以通过谷歌搜索来回答,但我这样做了,如果你不介意花一点时间,我想把它们弄清楚一点。SELECT ... FOR UPDATESET tx_isolation='READ-COMMITTED';
1赞 Bill Karwin 10/1/2017
SELECT ... FOR UPDATE应该工作一样,我猜你以不同的顺序执行了这些步骤。我不知道。
1赞 Bill Karwin 10/1/2017
如果使用 autocommit,则 read-commit 模式的作用与 repeatable-read 类似,因为每个语句都会启动一个新事务。但是,如果将 SELECT 作为较长事务的一部分执行,则需要使用 read-committed。
2赞 Bill Karwin 10/1/2017
COMMIT 释放 UPDATE 持有的锁。只要交易持续,锁定就会被保留。
0赞 John James 10/1/2017
谢谢,这对:)很有帮助