mysql – 什么时候使用SELECT … FOR UPDATE?

请帮助我理解SELECT … FOR UPDATE后面的用例。

问题1:以下是一个很好的例子,应该使用SELECT … FOR UPDATE?

给定:

>房间[id]
> tags [id,name]
> room_tags [room_id,tag_id]

> room_id和tag_id是外键

应用程序想要列出所有房间及其标签,但需要区分没有标签的房间和已删除的房间。如果不使用SELECT … FOR UPDATE,可能发生的是:

>最初:

> rooms contains [id = 1]
> tags contains [id = 1,name =’cats’]
> room_tags contains [room_id = 1,tag_id = 1]

>线程1:SELECT id FROM rooms;

> returns [id = 1]

>线程2:DELETE FROM room_tags WHERE room_id = 1;
>线程2:DELETE FROM rooms WHERE id = 1;
>线程2:[提交事务]
> Thread 1:SELECT tags.name FROM room_tags,tags WHERE room_tags.tag_id = 1 AND tags.id = room_tags.tag_id;

>返回一个空列表

现在线程1认为房间1没有标签,但在现实中,房间已被删除。为了解决这个问题,线程1应该选择id从房间FOR UPDATE,从而防止线程2从房间删除,直到线程1完成。那是对的吗?

问题2:什么时候应该使用SERIALIZABLE事务隔离与READ_COMMITTED与SELECT … FOR UPDATE?

答案应该是可移植的(不是数据库特定的)。如果不可能,请解释原因。

实现房间和标签之间一致性并确保房间在删除之后从不返回的唯一可移植方法是使用SELECT FOR UPDATE锁定它们。

但是在某些系统中,锁定是并发控制的副作用,并且您可以实现相同的结果,而不显式指定FOR UPDATE。

To solve this problem, Thread 1 should SELECT id FROM rooms FOR UPDATE, thereby preventing Thread 2 from deleting from rooms until Thread 1 is done. Is that correct?

这取决于数据库系统正在使用的并发控制。

> MyISAM在MySQL(和其他几个旧系统)在查询期间锁定整个表。
>在SQL Server中,SELECT查询将共享锁放置在他们检查的记录/页面/表上,而DML查询放置更新锁(稍后将升级为独占或降级为共享锁)。排它锁与共享锁不兼容,因此SELECT或DELETE查询将锁定,直到另一个会话提交。
>在使用MVCC的数据库(如Oracle,PostgreSQL,MySQL和InnoDB)中,DML查询创建记录的副本(以一种或另一种方式),一般来说读者不会阻止写者,反之亦然。对于这些数据库,SELECT FOR UPDATE会很方便:它将锁定SELECT或DELETE查询,直到另一个会话提交,就像SQL Server一样。

When should one use REPEATABLE_READ transaction isolation versus READ_COMMITTED with SELECT ... FOR UPDATE?

通常,REPEATABLE READ不禁止幻影行(在另一个事务中出现或消失的行,而不是被修改)

>在Oracle和早期的PostgreSQL版本中,REPEATABLE READ实际上是SERIALIZABLE的同义词。基本上,这意味着事务在启动后看不到更改。所以在这个设置中,最后一个Thread 1查询将返回房间,好像它从来没有被删除(这可能或可能不是你想要的)。如果您不想在删除后显示房间,您应该使用SELECT FOR UPDATE锁定行
>在InnoDB中,REPEATABLE READ和SERIALIZABLE是不同的东西:SERIALIZABLE模式下的读者在他们评估的记录上设置next-key锁,有效地防止对他们的并发DML。所以你不需要SELECT FOR UPDATE在可序列化模式,但确实需要他们在REPEATABLE READ或READ COMMITED。

请注意,隔离模式的标准规定您在查询中不会看到某些怪癖,但不定义如何(使用锁定或使用MVCC或其他方式)。

当我说“你不需要SELECT FOR UPDATE”我真的应该添加“由于某些数据库引擎实现的副作用”。

http://stackoverflow.com/questions/10935850/when-to-use-select-for-update

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:mysql – 什么时候使用SELECT … FOR UPDATE?