C# C中并发进程的SQL事务异常

C# C中并发进程的SQL事务异常,c#,transactions,isolation-level,C#,Transactions,Isolation Level,我们有一个C系统抛出了一个奇怪的东西,我们无法用SQL SQL2k5了解到底 情况是,我们有两个单独的进程同时运行在同一个表中,它们都在各自的事务中运行,在两个不同集群上的两个不同的服务COM+组件中运行。两者都在与Order和OrderItem SQL表对话。两者都在读提交隔离级别中运行 作业1:加载订单和一个或多个 将更多项目放入这些表中 作业2:发生的计划任务 每隔几分钟从所说的内容中进行选择 查找所有已删除的订单的表 已经完全处理过了 问题:我们发现,在过去八个月内,作业2对作业1的部分

我们有一个C系统抛出了一个奇怪的东西,我们无法用SQL SQL2k5了解到底

情况是,我们有两个单独的进程同时运行在同一个表中,它们都在各自的事务中运行,在两个不同集群上的两个不同的服务COM+组件中运行。两者都在与Order和OrderItem SQL表对话。两者都在读提交隔离级别中运行

作业1:加载订单和一个或多个 将更多项目放入这些表中

作业2:发生的计划任务 每隔几分钟从所说的内容中进行选择 查找所有已删除的订单的表 已经完全处理过了

问题:我们发现,在过去八个月内,作业2对作业1的部分加载订单有四次反应,在作业1完全完成之前,订单上的一个项目没有库存,处于已完成状态,因此作业可以看到订单的其余部分尚未加载

根据调查,当工作1正在进行时,我们无法进行:

从订单中选择*

一旦订单被插入其中。然而,我们可以做到:

在oi.orderid=o.id上选择*fromOrder o内部联接OrderItem oi

同时为什么会这样

在复制相同情况的调查中,我们无法让作业2看到从作业1部分创建的订单,它确实返回一些行,但从未返回作业1插入的订单。然而,这正是我们生活环境中正在发生的事情


有人知道为什么会发生这种情况吗?

我会尝试回滚作业1执行的一些工作,作为一个实验,以确认在回滚发生时,您认为包含在事务中的所有内容实际上都被删除。一、 和您一样,您可能会怀疑您永远无法从不同的事务中读取数据,这些数据在使用read COMMITTED时会通过回滚删除。您能够读取行的事实表明,其中一些行可能位于事务上下文之外

我的下一个想法是回顾阅读承诺的含义。这个隔离级别可以确保您正在读取的数据已经由一个事务提交,但不一定确保它仍然不能因为另一个事务而更改。与此相比,可重复读取(REPEATABLE READ)在事务结束前所有数据都保持锁定状态,或可序列化(SERIALIZABLE),其行为方式似乎所有事务都是按顺序执行的。我怀疑,如果您将锁定更改为可序列化,则不会出现限制性最强的特定问题,但这可能有点过头了

与其他隔离级别相比,在考虑了readcommitted的含义之后,我怀疑您在该隔离级别中看到的行为是自然的,因为您插入的行实际上是事务结束时仍然存在的行。我认为readcommitted并不是为了确保查询返回一组完整的行,这将需要SERIALIZABLE强加的范围锁,而是为了确保您正在读取的单个行已完全插入,因此您不会读取部分行。我可能错了,但考虑到你描述的行为,这是我的怀疑。如果您需要确保整个行集合是完整的,我认为您需要可序列化的隔离


哪个事务需要序列化?显然,如果它们都是可序列化的,那么应该可以。但可能只使其中一个可序列化,并且仍然可以获得正确的行为。目前,我的思维能力还不能决定什么才是真正需要序列化的,但也许其他人的一些评论会提供更多信息。

问题是,当您打开事务并添加几行时,这些行会被锁定,直到事务提交

当您选择*时,您正在执行一个包含锁定行的选择,因此在允许您选择之前,您必须通过提交或回滚事务来解锁这些行