【发布时间】:2011-02-08 00:11:19
【问题描述】:
我有一个从多个线程调用的进程,它执行以下操作:
- 开始交易
- 通过查找
IsProcessed=0和提示(UPDLOCK, HOLDLOCK, READPAST)的下一行从工作表中选择工作单元 - 处理工作单元(C# 和 SQL 存储过程)
- 提交事务
这样做的想法是一个线程浸入池中以获取“下一个”工作,并对其进行处理,并且锁在那里确保单个工作不会被处理两次。 (顺序无关紧要)。
这几个月来一直运行良好。直到今天,当我碰巧意识到尽管启用了快照隔离并将其设置为数据库级别的默认设置,但实际的事务创建代码是手动设置了“ReadCommitted”的隔离级别。
我及时将其更改为“快照”,当然立即收到以下消息:
您只能在 READ COMMITTED 或 REPEATABLE READ 中指定 READPAST 锁
锁定行的主要原因是“标记行”,这样当应用标记的事务被提交时,“标记”将被移除,而锁定似乎是最好的方法,因为除了这些线程之外,不会以其他方式读取此表。如果我要使用 IsProcessed 标志作为锁,那么大概我需要先进行更新,然后选择我刚刚更新的行,但我需要使用 NOLOCK 标志来知道是否有任何其他线程设置了连续标记。
听起来有点乱。最简单的选择是完全放弃快照隔离模式,但第 3 步的设计需要它。
关于解决这个问题的最佳方法有什么好的想法吗?
【问题讨论】:
标签: sql-server concurrency transactions snapshot isolation-level