【发布时间】:2018-06-27 17:30:28
【问题描述】:
假设我在 SQL Server 中有一个表,用作需要处理的项目的队列。像这样的:
Id (bigint)
BatchGuid (guid)
BatchProcessed (bit)
...
...以及描述需要处理的项目的其他一些列等。因此,有许多正在运行的消费者根据需要将记录添加到此表中以指示需要处理的项目。
现在假设我有一份工作,负责从该表中获取一批项目并进行处理。假设我们想让它一次处理 10 个。现在还假设该作业可以同时运行多个实例,因此它同时访问表(以及可能正在向队列添加新记录的任何其他消费者)。
我打算做这样的事情:
using(var tx = new Transaction(Isolation.Serializable))
{
var batchGuid = //newGuid
executeSql("update top(10) [QUeueTable] set [BatchGuid] = batchGuid where [BatchGuid] is null");
var itemsToProcess = executeSql("select * from [QueueTable] where [BatchGuid] = batchGuid");
tx.Commit()
}
所以基本上我要做的是启动一个可序列化的事务,用特定的 GUID 标记 10 个项目,然后获取这 10 个项目,然后提交。
这是一个可行的策略吗?我相信可序列化的隔离级别基本上会锁定整个表以防止读/写直到事务完成 - 这是正确的吗?基本上事务会阻塞表上的所有其他读/写操作?我相信这就是我在这种情况下想要的,因为我不想读取脏数据,并且我不希望并发运行的作业在标记要处理的 10 个批次时相互踩踏。
任何关于我是否在正确的轨道上的见解将不胜感激。如果有更好的方法来实现这一点,我也欢迎其他方法。
【问题讨论】:
-
这是一篇很棒的文章,Remus。非常翔实!谢谢。
标签: c# sql-server transactions isolation-level