确保房间和标签之间的一致性并确保在删除房间后绝不返回房间的唯一可移植方法是使用锁定它们
SELECt FOR UPDATE。
但是,在某些系统中,锁定是并发控制的副作用,并且无需
FOR UPDATE显式指定即可获得相同的结果。
要解决此问题,线程1应该
SELECT id FROM rooms FORUPDATE,从而防止线程2从删除rooms直到线程1完成。那是对的吗?
这取决于您的数据库系统正在使用的并发控制。
MyISAM
在MySQL
(和其他几个老系统)则锁定整个表进行查询的时间。在中
SQL Server
,SELECT
查询将共享锁放置在他们检查过的记录/页面/表上,而DML
查询则将更新锁放置(随后将其升级为互斥或降级为共享锁)。互斥锁与共享锁不兼容,因此SELECT
或DELETE
查询将一直锁定,直到提交另一个会话为止。在数据库在使用
MVCC
(如Oracle
,PostgreSQL
,MySQL
用InnoDB
),一个DML
查询创建记录的副本(以一种或另一种方式),一般读者不会阻止作家,反之亦然。对于这些数据库,aSELECT FOR UPDATE
会派上用场:它将锁定一个SELECT
或一个DELETE
查询,直到提交另一个会话为止,就像这样SQL Server
做一样。
当一个人应该使用
REPEATABLE_READ的事务隔离与READ_COMMITTED用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”时,我确实应该添加“因为某些数据库引擎实现的副作用”。



