尝试在单个TransactionScope
下同时发出两个查询时,我的应用程序抛出错误。
例如,使用Entity Framework,我将创建两个单独的DbContext
实例,并在同一ToListAsync
中对它们中的每个实例启动异步操作(即TransactionScope
),然后用Task
等待两个返回的Task.WhenAll
。目的是在数据库服务器上同时运行两个I / O绑定操作时,将这两个查询尽快发送到服务器,并将主请求线程释放回池中。
这种方法有时会引发错误:
该操作对于交易状态无效
这是可预测的比赛情况吗?例如,如果我在开始第二项任务(或其余的N-1项任务)之前await
进行了第一项任务,那么在没有竞争条件的情况下,一切并行运行良好。但是,如果我不等待第一个任务,而是同时启动所有剩余任务,则似乎其中两个(或多个)都在尝试同时建立事务和TransactionScope
实例,如果不是数据库服务器本身,就会感到困惑。
我读了一篇文章,暗示在单个TransactionScope
中打开两个连接是无效的。虽然我不认为是这种情况(在同一笔交易中打开两个连接只会将其升级为分布式交易),但我确实相信这会导致某种竞争状况,如我所描述。
由上述情况引起的另一个问题确实很糟糕。分布式事务失败后,每次尝试打开我的服务器上的连接都会导致以下错误:
已完成分布式事务。将此会话注册为新事务或NULL事务。
此错误发生在不相关代码(仍在同一运行的Web应用程序中)的DbContext
的全新实例中,这些实例没有包装在任何类型的事务中,这向我提示连接池中的连接具有已损坏。