简体   繁体   English

在快照隔离模式下无法使用READPAST

[英]Cannot use READPAST in snapshot isolation mode

I have a process which is called from multiple threads which does the following: 我有一个从多个线程调用的进程,它执行以下操作:

  1. Start transaction 开始交易
  2. Select unit of work from work table with by finding the next row where IsProcessed=0 with hints (UPDLOCK, HOLDLOCK, READPAST) 通过查找下一行IsProcessed=0并使用提示(UPDLOCK, HOLDLOCK, READPAST)从工作表中选择工作单元
  3. Process the unit of work (C# and SQL stored procedures) 处理工作单元(C#和SQL存储过程)
  4. Commit the transaction 提交交易

The idea of this is that a thread dips into the pool for the "next" piece of work, and processes it, and the locks are there to ensure that a single piece of work is not processed twice. 这样做的想法是,一个线程进入池中进行“下一步”工作,并对其进行处理,并且锁定在那里以确保单个工作不会被处理两次。 (the order doesn't matter). (顺序无关紧要)。

All this has been working fine for months. 这几个月一直都很好。 Until today that is, when I happened to realize that despite enabling snapshot isolation and making it the default at the database level, the actual transaction creation code was manually setting an isolation level of "ReadCommitted". 直到今天,当我碰巧意识到尽管启用快照隔离并使其成为数据库级别的默认值时,实际的事务创建代码却手动设置了“ReadCommitted”的隔离级别。

I duly changed that to "Snapshot", and of course immediately received below message: 我正式将其更改为“快照”,当然立即收到以下消息:

You can only specify the READPAST lock in the READ COMMITTED or REPEATABLE READ 您只能在READ COMMITTED或REPEATABLE READ中指定READPAST锁

The main reason for locking the row was to "mark the row" in such a way that the "mark" would be removed when the transaction that applied the mark was committed and the lock seemed to be the best way to do this, since this table isn't read otherwise except by these threads. 锁定行的主要原因是“标记行”,以便在提交应用标记的事务时删除“标记”并且锁定似乎是执行此操作的最佳方式,因为这除非通过这些线程,否则不会读取表。 If I were to use the IsProcessed flag as the lock, then presumably I would need to do the update first, and then select the row I just updated, but I would need to employ the NOLOCK flag to know whether any other thread had set the flag on a row. 如果我使用IsProcessed标志作为锁,那么我可能需要先进行更新,然后选择刚刚更新的行,但我需要使用NOLOCK标志来知道是否有其他线程设置了在一排上的标志。

All sounds a bit messy. 所有听起来都有点乱。 The easiest option would be to abandon the snapshot isolation mode altogether, but the design of step #3 requires it. 最简单的选择是完全放弃快照隔离模式,但步骤#3的设计需要它。

Any bright ideas on the best way to resolve this problem? 关于解决这个问题的最佳方法有什么好主意吗?

change the isolation level of the particular transaction to something other than the default read committed (which in your case you have defaulted to behave in snapshot mode). 将特定事务的隔离级别更改为默认读取提交之外的其他内容(在您的情况下,您已默认在快照模式下执行操作)。 Then you can leave other work in the database in snapshot, but this particular workflow in your code will be something other than snapshot. 然后,您可以在快照中将其他工作留在数据库中,但代码中的此特定工作流将不是快照。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM