2017-10-01 25 views
1

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

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

如何使每个查询等待读写直到写入完成。

回答

1

使用READ-COMMITTED事务将查看最新的提交。更改,并使用SELECT ... 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

事实上,我测试了它,它的工作原理,如果你不介意,你能否迅速向我解释一两件事情。首先,为什么'SELECT ... FOR UPDATE'不起作用? 其次,我尝试不使用'SET tx_isolation ='READ-COMMITTED';'它仍然有效。最后一个提交使它无法写入,直到它完成(虽然默认情况下不是这样)。我知道其中的一些可以通过Google搜索来回答,但是我这样做并且想要澄清它们,如果您不介意花费一点时间。 –

+1

'SELECT ... FOR UPDATE'应该可以工作,我想你是按照不同的顺序完成的。我不知道。 –

+1

如果您使用自动提交,读取提交模式的行为就像可重复读取一样,因为每个语句都会启动一个新的事务。但是,如果您将SELECT作为更长事务的一部分,则需要使用read-committed。 –