【发布时间】:2014-05-12 15:24:13
【问题描述】:
如果我们有一个带有子 SELECT 的 UPDATE,子查询是否可以在 READ COMMITTED 隔离下并发执行?
换句话说,以下是否存在竞争条件:
update list set [state] = 'active'
where
id = (select top 1 id from list where [state] = 'ready' order by id)
换句话说,如果许多连接同时执行此 SQL,我们能否保证每次调用实际上更新一行(只要存在“就绪”状态的行)?
【问题讨论】:
-
将多个操作放入单个语句中对并发性毫无帮助。语句不提供与并发相关的保证。
-
这是不正确的。在 READ COMMITTED 下,一次为一个 SELECT 语句获取和释放共享锁。但我不确定该示例采用什么顺序锁。我也很高兴将 begin tran 和 commit 放在它周围,尽管我很确定这没有什么区别,因为事务永远不会少于单个语句。
-
没有。 READ COMMITTED 尽快释放锁,通常在每一行之后。对于没有未提交数据的页面,它甚至根本不需要锁。这是一个鲜为人知的优化。 “我也很高兴将 begin tran 和 commit 放在一起”这是另一个误解,认为这会改变任何事情。在自动提交模式下,语句仍然在隐式事务下运行。在这方面你是对的。
-
我想知道为什么 MSDN 文档会如此明确地指出“因为共享锁 [in REPEATABLE READ] 被持有到事务结束而不是在每个语句结束时被释放 [强调我的],并发低于默认的 READ COMMITTED 隔离级别。”
-
这是一个关于 REPEATABLE READ 的声明,它永远使用 S-locks 来确保数据是稳定的。 READ COMMITTED 不保证数据稳定。它几乎没有任何保证。
标签: sql-server concurrency isolation-level