如何使TransactionScope在多线程中正常工作

3

首先感谢您关注这个问题;是否有办法在c#中实现这样的事务

using (Transactionscope x=new Transactionscope ())
{

   Thead A()=> Independent Transactionscope()  A(Insert into table X )

   Thead B()=> Independent Transactionscope()  B(Insert into table Y )

   Thead C()=> Independent Transactionscope()  C(Insert into table Z )

   Thread.WaitAll(A,B,C)

  commit big transaction x/ rollback big transaction x
}

在事务中执行的SQL命令必须全部针对同一SQL连接执行。因此,将它们分成线程是没有意义的;它们无论如何都将按顺序执行。 - John Wu
1
在 .Net Framework 上,@JohnWu 指出可以使用 TransactionScope 通过 MS DTC 来启动分布式事务,因此不需要所有命令都与相同的 Sql 连接相关联。事实上,TransactionScope 还可用于其他 ACID 资源,如队列或事务性文件系统。 - StuartLC
@StuartLC 很有趣,也很聪明。我没有想到要绑定 MSDTC。问题是:如果 OP 在同一数据库实例中为(子)事务执行此操作,是否存在线程相互死锁的风险? - John Wu
@JohnWu 是的,DTC可能会导致许多锁定相关问题,并且经常降低企业的可扩展性。看起来现在大多数人更喜欢查看补偿事务,或将真相源从RDMS移出到事件和命令中(Actor模型、事件溯源等)。 - StuartLC
1个回答

2
请注意,在 .Net Core 上目前不支持分布式事务,只有在 .Net Framework 上支持。
为了使用 TransactionScope 跨多个线程,您需要使用 DependentClone 将线程连接到父 TransactionScope
步骤如下:
  1. 在主线程上启动一个 TransactionScope
  2. 在创建每个线程之前,使用 DependentClone 创建一个 DependentTransaction,然后将此实例传递给新线程。
  3. 在子线程上,您可以使用 TransactionScope(DependentTransaction) 构造函数重载来创建链接的 TransactionScope,在其中子线程可以执行本地事务。
  4. 当每个子线程上的工作成功完成时,然后提交线程的 TransactionScopeDependentTransaction
  5. 在主线程上,等待所有线程完成,然后提交根 TransactionScope

还有一些注意事项:

  1. 在多个线程上使用 DependentTransaction 会立即要求使用 MSDTC。
  2. 在大型 DTC 事务下使用多个线程不会使插入到同一表格变得更快(对于此,请使用 SqlBulkCopy),您需要衡量并行插入到不同表格、在 DTC 事务下的锁定开销或是否返回任何性能优势。
  3. 如果您正在使用 async,则需要 TransactionScopeAsyncFlowOption.Enabled

有关 Transction Scope 的更多信息,请参见此处。


太好了!谢谢你的指导~ - frank_liu
如果可能的话,我通常会建议避免使用DTC。例如,如果您正在对同一数据库进行大量连接工作,则建议使用单个事务 - 可以在单个连接上使用SqlTransaction,或者如果使用多个(连接池)连接的Transaction Scope,请确保在继续下一个连接之前关闭每个连接 - 这通常会落在轻型事务管理器上。 - StuartLC
在单个数据库上,你通常最好花时间优化单个线程的性能/按顺序完成工作,而不是试图在一个总事务下并行处理工作。 - StuartLC
TransactionScopeAsyncFlowOption 更适用于异步/等待目的,因为继续执行和最终的 TransactionScope 完成 + 处置可能在不同于 TS 开始的线程上执行。然而,我怀疑异步调用必须按顺序完成,即尝试并行化异步代码(例如 Task.WhenAll)可能需要与 DependentTransaction 相同的处理,因为连续可能会在不同的线程上同时完成。 - StuartLC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接