问题描述:

系统中多个功能不定期出现“Unable to get error message (6107) (0).”错误,即分布式事务超时,但报出错误的部分功能根本没有使用分布式事务。

原因分析:

推测是存在分布式事务未提交的情况,回到线程池后被复用造成的,例如:

系统中A功能存在分布式事务未提交的问题,处理A功能的线程执行完成后回到线程池,B功能复用了处理A功能的线程,A功能未提交的分布式事务将B功能的代码也包含进去了,依次类推可能还有C、D等功能,直到A功能开启的分布式事务超时报出6107错误,而报错的B或C、D等功能本身是没有问题的。

Demo验证:

   1:      ThreadPool.SetMinThreads(1, 1);
   2:      ThreadPool.SetMaxThreads(1, 1);
   3:   
   4:      ThreadPool.QueueUserWorkItem((x) =>
   5:      {
   6:          Console.WriteLine("33: " + Thread.CurrentThread.ManagedThreadId);
   7:          TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 10));
   8:          using (OracleConnection conn = new OracleConnection(connstr))
   9:          {
  10:              conn.Open();
  11:              var cmd = conn.CreateCommand();
  12:              cmd.CommandText = @"update workitem set name = 'yyxx' where workitemid = '64365dc4-41d7-4057-af68-012d552660e2'";
  13:              cmd.ExecuteNonQuery();
  14:              conn.Close();
  15:          }
  16:          Thread.Sleep(100);
  17:          Console.WriteLine("33: end");
  18:      });
  19:              
  20:      ThreadPool.QueueUserWorkItem((x) => {
  21:          Console.WriteLine("44: " + Thread.CurrentThread.ManagedThreadId);
  22:          try
  23:          {
  24:              while (true)
  25:              {
  26:                  using (OracleConnection conn = new OracleConnection(connstr))
  27:                  {
  28:                      conn.Open();
  29:                      var cmd = conn.CreateCommand();
  30:                      cmd.CommandText = @"update workitem set name = 'xxyy' where workitemid = '68265741-4433-42e9-b7e7-63ae1ce8bbc8'";
  31:                      cmd.ExecuteNonQuery();
  32:                      conn.Close();
  33:                  }
  34:                  Thread.Sleep(100);
  35:              }
  36:          }
  37:          catch (Exception e)
  38:          {
  39:              Console.WriteLine(e);
  40:          }
  41:          Console.WriteLine("44: end");
  42:      });


解决方法:

使用HttpModule 分别在beginRequest和endRequest中判断是否已包含了事务上下文

如果beginRequest中没有事务,endRequest时有未提交事务,则说明当前请求对应的是问题源头;

如果beginRequest和endRequest都有,说明当前请求是线程复用后的受害者。

示例如下:

   1:          protected void context_EndRequest(object sender, EventArgs e)
   2:          {
   3:              Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
   4:              Type t = typeof(Transaction);
   5:              FieldInfo field = t.GetField("complete", BindingFlags.Instance | BindingFlags.NonPublic);
   6:              if (Transaction.Current != null)
   7:              {
   8:                  bool isComplete = (bool) field.GetValue(Transaction.Current);
   9:                  if (!isComplete)
  10:                  {
  11:                      Debug.WriteLine(
  12:                          string.Format(@"Creation Time: {0}\r\nDistributedIdentifier:{1}\r\nLocalIdentifier:{2}",
  13:                              Transaction.Current.TransactionInformation.CreationTime,
  14:                              Transaction.Current.TransactionInformation.DistributedIdentifier,
  15:                              Transaction.Current.TransactionInformation.LocalIdentifier));
  16:                      //Transaction.Current.Rollback();
  17:                      //Transaction.Current.Dispose();
  18:                  }
  19:              }
  20:          }


.NET分布式事务未提交造成6107错误或系统被挂起的问题分析定位的更多相关文章

  1. SQLServer之创建事务未提交读

    未提交读注意事项 使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 指定会话的锁定级别. 一次只能设置一个隔离级别选项,而且设置的选项将一直对那个 ...

  2. 记一次mysql事务未提交导致锁未释放的问题

    记一次mysql事务未提交导致锁未释放的问题 ## 查看未提交的事务(3秒内未操作的事务) SELECT p.ID AS conn_id, P.USER AS login_user, P.HOST A ...

  3. MySQL事务未提交导致整个表锁死

    问题及说明: 当一个SQL事务执行完了,但未COMMIT,后面的SQL想要执行就是被锁,超时结束:报错信息如下: mysql> ERROR 1205 (HY000): Lock wait tim ...

  4. SpringMVC+Hibernate架构save方法事务未提交

    今天同事遇到一个问题,一起研究,最后解决,让我对spring的事务管理又加深了印象. 先简单说一下项目:项目是Spring和Hibernate集成的JavaEE项目,MVC架构. 外包在service ...

  5. 分布式事务二阶提交DTS系统

    前端时间写新交易系统时,经常碰到事务一致性问题,网上搜了一下,有一些解决方法,采用了扫表补偿的方式来完成,刚开始只有几个接口需要处理,工作量还可以,但是后续随着需求的增加,这些场景错综复杂,导致大量时 ...

  6. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

  7. SQL Server中的事务与其隔离级别之脏读, 未提交读,不可重复读和幻读

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

  8. 同一个事务里 查询 已删除可是未提交的数据[bug记录]

    前几天犯了个低级错误.在一个事务方法里老是查询不到某条记录,可是debug卡住时,用db工具查.又能查出值. 经过一番折腾,原来是我在同一个事务里 查询 了已删除可是未提交的数据.当然查询不到了! . ...

  9. 【故障处理】分布式事务ORA-01591错误解决

    [故障处理]分布式事务ORA-01591错误解决 1  BLOG文档结构图       2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你 ...

随机推荐

  1. codeforces #Round354-div2-D(BFS)

    题目链接:题目链接 题意:一个n*m的区域,每个格子都有上下左右四个门,相邻的两个格子A可以通向B当且仅当A对B的门和B对A的门都打开,问从起点S到终点T需要的最短时间 #include<bit ...

  2. matlab print,disp,fprint,fscan

    http://wenku.baidu.com/link?url=ZvpdbnbozLtaSQA011ZBl5tbpqN62nu8VH-sBZYDQkv4KaaIwnaSXg5vPDgxTjudG-Qn ...

  3. LeetCode Combination Sum III (DFS)

    题意: 在1-9这9个数字中选择k个出来,若他们的和为n,则加入答案序列,注意升序. 思路: 用DFS的方式,每次决定一个数字,共决策k次.假设上个决策是第i位为5,那么i+1位的范围就是6-9. c ...

  4. Day04_JAVA语言基础第四天

    1.循环(掌握) 1.什么时候使用(理解) 如果我们发现有很多重复内容的时候就要使用循环 2.好处(理解) 让我们的代码看起来更精炼了 3.循环的组成(理解) 1 初始化条件:一般定义的是一个初始变量 ...

  5. C# 扩展方法 总结

    扩展方法是静态方法,它是类的一部分,但实际上没有放在类的源代码中. 设计一个Money类 public class Money { private decimal amount; public dec ...

  6. 关于 System.IO.FileAttributes 的 Reparse Points

    关于Reparse Points找到下面的解释,要是能有更进一步的解释说明就更好了 Reparse Points其实是一个用户自定义的数据集合,它可以包含在一个文件或目录中.这种格式的数据能够被特定的 ...

  7. iOS7中如何去除UINavigationbar下边的那条黑线

    做项目过程中遇到要去掉导航栏下面的一条黑线,从网上找到的一个方法 默认UINavigationbar样式 准备用于替换的背景 替换后的效果 if ([self.navigationController ...

  8. [转载] C++位运算:将一个4字节整数的二进制表示中的001替换为011

    #include <iostream> #include <assert.h> /** * Key: * * get someone bit: num & (mode1 ...

  9. discuz使用

    1.discuz登陆错误过多,后台删除ip SELECT * FROM `lang_common_admincp_session` 2.Discuz与UCenter通信失败的解决方法 应用与 UCen ...

  10. yii2数据修改|联查

    model 层   联查 $con = Yii::$app->db; $re = $con->createCommand("select * from ads LEFT JOIN ...