READ UNCOMMITTED 与 FOR UPDATE 的替代方法

Posted

技术标签:

【中文标题】READ UNCOMMITTED 与 FOR UPDATE 的替代方法【英文标题】:Alternative To READ UNCOMMITED With FOR UPDATE 【发布时间】:2012-08-22 03:08:23 【问题描述】:

我们有 2 个脚本/mysql 连接,它们从表中获取行。一旦一个脚本抓取了一些行,其他脚本就不能访问这些行。

到目前为止,我得到的似乎是这样的:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
START TRANSACTION

SELECT * FROM table WHERE result='new' FOR UPDATE

// Loop over update
UPDATE table SET result='old' WHERE id=...

COMMIT

据我了解,同一个连接可以读取脏数据,但由于行被锁定,其他连接不应该能够读取。这是正确的吗?

还有没有更好的方法来保证每一行在两个脚本都运行时只能是SELECT 一次?

编辑: 哦...引擎是 Innodb

编辑:另外我想尽量避免死锁,除非它们真的没有效果,我可以为它们做准备并重新运行查询。

【问题讨论】:

【参考方案1】:

SELECT ... FOR UDATE 在行上设置排他锁,如果不可能,它会等待锁被释放,SELECT ... FOR UDATE 语句的主要目的是防止其他人在您操作它们时读取某些行。

如果我的问题是正确的,“脏数据”是指那些锁定的行吗? 不明白为什么称它们为“脏”,因为它们只是被锁定,但实际上在同一个事务中,您可以读取已锁定的行(显然)。

关于你的第二个问题

还有没有更好的方法来保证每一行只能 SELECT 一次同时运行两个脚本?

SELECT ... FOR UDATE 保证在每一时刻某些行只能在一个事务中读取。只要此声明是专门为此目的而设计的,我就没有更好的方法来做到这一点。

【讨论】:

我忘了在最初的问题中提到我也想避免死锁......这就是使用READ UNCOMMITED的原因。担心死锁并提前做好准备是愚蠢的吗? 我看不出有什么理由担心死锁。可能我没有看到整个情况......

以上是关于READ UNCOMMITTED 与 FOR UPDATE 的替代方法的主要内容,如果未能解决你的问题,请参考以下文章

Read Uncommitted

为啥使用 READ UNCOMMITTED 隔离级别?

如何测试 MySql READ UNCOMMITTED 对 nolock 的使用

在 READ UNCOMMITTED 事务期间使用索引导致无法获取更新锁

MySQL - READ UNCOMMITTED 隔离级别是不是使用锁?

解决“set transaction isolation level read uncommitted;“命令无法修改MySQL数据库隔离级别的问题