【问题标题】:how TransactionScope work with multi-threadsTransactionScope 如何与多线程一起工作
【发布时间】:2019-12-19 05:22:05
【问题描述】:

您好首先感谢您对这个问题的关注; 有没有办法在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 连接执行。因此,将它们分成线程是没有意义的;无论如何都会被连续执行。
  • @JohnWu on .Net Framework,TransactionScope 可用于通过 MS DTC 启动分布式事务,因此无需将所有命令与同一个 Sql Connection 关联。事实上,TransactionScope 可以用于其他 ACID 资源,例如队列或事务文件系统。
  • @StuartLC 有趣又聪明。我没有想到要绑定 MSDTC。问题:如果 OP 对同一个数据库实例中的(子)事务执行此操作,线程是否有可能相互死锁?
  • @JohnWu 是的,DTC 会导致很多与锁定相关的问题,并且通常会降低企业的可扩展性。似乎现在大多数人更喜欢查看有偿交易,或者将事实来源从 RDMS 转移到事件和命令中(Actor Model、Event Sourcing 等)

标签: c# transactionscope


【解决方案1】:

请注意,分布式事务目前在 .Net Core 上为 not supported,仅在 .Net Framework 上。

为了使用TransactionScope 跨越多个线程,您需要使用DependentClone 将线程绑定到父TransactionScope

步骤如下:

  1. 在您的主线程/第一个线程上启动 TransactionScope
  2. 就在创建每个线程之前,使用DependentClone 创建一个DependentTransaction,然后将此DependentTransaction 实例传递给新线程。
  3. 在子线程上,您可以使用TransactionScope(DependentTransaction)构造函数重载创建一个链接的TransactionScope,子线程可以在其中执行本地事务。
  4. 由于每个子线程的工作都成功完成,然后提交线程TransactionScopeDependentTransaction
  5. 在主线程上,等待所有线程完成,然后提交根TransactionScope

还有一些注意事项:

  1. 在多个线程上使用 DependentTransaction 将立即需要使用 MSDTC。
  2. 在大型 DTC 事务下使用多个线程不会更快地插入同一个表(使用 SqlBulkCopy),您需要衡量是否并行插入到不同的表中,同一数据库下DTC 事务保证锁定开销或返回任何性能优势。
  3. 如果您使用的是async,那么您将需要TransactionScopeAsyncFlowOption.Enabled

更多关于Transction Scope here

【讨论】:

  • 太棒了!谢谢你的指导~
  • 如果可能,我通常会建议不要使用 DTC,例如如果您在同一个数据库上进行大量连接工作,那么我建议您使用单个事务 - 在单个连接上使用 SqlTransaction,或者如果将事务范围与多个(连接池)连接一起使用,请确保关闭在继续下一个连接之前进行每个连接 - 这通常会在轻量级事务管理器上结束。
  • 在单个数据库上,您的时间通常最好花在优化单个线程上的性能/按顺序完成工作,而不是尝试在伞状事务下并行工作。
  • TransactionScopeAsyncFlowOption 更多地用于异步/等待目的,因为延续和最终的 TransactionScope 完成 + 处置可能在与 TS 启动的线程不同的线程上执行。但是我怀疑异步调用必须按顺序完成,即尝试并行化异步代码(例如Task.WhenAll)可能需要与DependentTransaction 相同的处理,因为延续可以在不同的线程上同时完成。
猜你喜欢
  • 2020-07-31
  • 2015-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
  • 2014-09-09
  • 2021-11-14
  • 1970-01-01
  • 2015-10-28
相关资源
最近更新 更多