Joe*_*ool 7 sql-server concurrency
下面两条SQL语句在原子性和隔离性上有什么区别吗?
批次A:
UPDATE Orders
SET InProgress = 1
WHERE Completed = 0
Run Code Online (Sandbox Code Playgroud)
和
批次 B:
UPDATE Orders
SET InProgress = 1
WHERE OrderID in (SELECT OrderID FROM Orders WHERE Completed = 0)
Run Code Online (Sandbox Code Playgroud)
在 READ COMMITTED 的 SQL Server 中默认隔离级别下,我相信您可能会遇到批处理 B 的并发问题。在子查询选择之后,另一个进程可以在某些选定行上将 Completed 设置为 1,但批处理 B 不知道它仍然会在它们上设置 InProgress = 1。
但是A批次呢?在批处理 A 将 InProgress 设置为 1 之前,其他进程是否可以在任何行上更改 Completed?或者它是原子的并且与任何其他进程隔离?
另一种提问方式是,何时在 READ COMMITTED 隔离下的表上放置更新(或排他)锁?在批处理 A 中,我假设它发生在 WHERE 子句被评估之前,使批处理原子化和隔离。B批次呢?在评估子查询之前或之后,更新/排他锁是放在 Orders 上的吗?
Rem*_*anu 11
通过使用(至少)U 锁(更新锁,请参阅锁兼容性),在发现期间始终稳定符合更新条件的行。何时真正更新它们,U 锁升级为 X 锁。由于这种稳定性,行不会消失,也不能在发现和更新之间进行修改。第二个 UPDATE 语句也不能发现同一行:并发 UPDATE 必须等待第一个提交,即使它只需要“检查”该行而不实际更新它。所以批次 A 是 100% 防弹的。对于 Batch B,大多数时候引擎会理解您的意思并使用更新语义扫描连接(您的 IN 子句将在查询规范化期间重写为 JOIN)。
根据计划是否需要万圣节保护,行为也有所不同,但这仅意味着 U 锁的使用寿命更长。
作为一般评论,您显示的查询是使用表行状态的标志查询,您应该在其中使用 queues。的并发性SET InProgress = 1 WHERE Completed = 0基本上是 1,因为它总是需要扫描。使用事件队列将请求发送到转换状态的等效解决方案将基本上扩展 X 个 CPU。
| 归档时间: |
|
| 查看次数: |
2437 次 |
| 最近记录: |