博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从报错“无效操作,连接被关闭”探究Transaction的Timeout超时机制
阅读量:4968 次
发布时间:2019-06-12

本文共 2677 字,大约阅读时间需要 8 分钟。

1、报错如下:Invalid Operation the connection is closed,无效操作,连接被关闭。这个错误是并不是每次都报,只有在复杂操作、大事务的情况下才偶然报出来。

stackOverflow上有很多关于这个问题的讨论,例如这个:,但较零散,全扫了一遍之后,我仍然有如下疑问:

1)怎么看TransactionScope里的Timeout到底是多少,比如通过TransactionOptions.Timeout = new TimeSpan(0,0,3)设置之后,怎么知道TransactionScope里的超时就是3s?

2)默认MaxTimeout=10m,怎么才能设置任意值?

3)嵌套事务的外层超时是否包括所有内层事务的时间?

4)超时机制是怎么起作用的?

通过Reflector之类的工具查看源码,终于有了初步的理解,不对的地方,请大家指正!

 

2、怎么看TransactionScope里的Timeout?

用调试器逐级展开TransactionScope实例如下:

scope->committableTransaction->base->internalTransaction->absoluteTimeout //注:这是展开过程,不是代码

这个absoluteTimeout就是实际结果,但往往与你设置的值不匹配,比如:

TimeSpan absoluteTimeout
3s 5
10s 19
1m 117
10m 1171
30m 3515
1h 7031

看起来是经过某个算法转换后的值,这个算法写在TransactionTable.TimeoutTicks()里:

internal long TimeoutTicks(TimeSpan timeout){  if(timeout != TimeSpan.Zero) {    return (timeout.Ticks / 10000L >> 9) + this.ticks;  }   return 9223372036854775807L;}

这就清楚了,再加上上面那张对照表,就可以通过absoluteTimeout清楚知道设置是否生效。

 

3、默认MaxTimeout=10m,怎么才能设置任意值?

1)先说一下这个10m怎么来的?

TransactionScope.ctr()->TransactionManager.ValidateTimeout()->MaximumTimeout->MachineSettingsSection.MaximumTimeout

这个属性先读取c:\windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config里的值://注意对应的framework的版本!

当然,我查看下来,所有版本的machine.config里默认都没有这个节点。那么退一步,由Attribute设置默认值:

[ConfigurationProperty("maxTimeout", DefaultValue = "00:10:00")]public TimeSpan MaxTimeout

 

2)再说一下怎么改成任意值?

2.1)修改machine.config,优点:方便,缺点:会影响机器上的所有事务。方法是在全局的machine.config里添加对应节点,注意在自己的app/web.config里添加<machineSettings>节点会报错。

2.2)用反射(神器)!优点:只作用于自己的事务,缺点:用反射、稍麻烦、稍慢。

static void ChangeMaximumTimeout() { Type t = typeof(TransactionManager); FieldInfo f = t.GetField("_cachedMaxTimeout", BindingFlags.NonPublic | BindingFlags.Static); f.SetValue(null, true); f = t.GetField("_maximumTimeout", BindingFlags.NonPublic | BindingFlags.Static); f.SetValue(null, new TimeSpan(2, 0, 0));}

这么写是因为最终大家取的都是static类里的static属性:

public static class TransactionManager { public static TimeSpan MaximumTimeout {  get {   if(!_cachedMaxTimeout) {     _maximumTimeout = MachineSettings.MaxTimeout;   }   return _maximumTimeout; }}}

贴出来,一目了然!

 

4、嵌套事务的外层超时是否包括所有内层事务的时间?

我理解外层超时包含所有内层事务的执行时间,测试代码如下:

option.Timeout = new TimeSpan(0,0,3);using(var scope = new TransactionScope(TransactionScopeOption.Required, option)) { Thread.Sleep(2000); option1.Timeout = new TimeSpan(0,0,5); using(var scope1 = new TransactionScope(TransactionScopeOption.Required, option)) {  Thread.Sleep(500); // 800以上基本就报超时错误了}}

 

5、超时机制是怎么起作用的?

1)对于非根(committableTransaction == null)的事务,会构造一个scopeTimer = new Timer(timeSpan, TimeoutCallback)来触发超时回滚;

2)对于committableTransaction != null的根事务,超时机制尚未找到,有待补充完整。

转载于:https://www.cnblogs.com/AlexanderYao/p/4065575.html

你可能感兴趣的文章
MongoDB学习笔记Day1
查看>>
[.NET] - EventSource类的使用
查看>>
过滤URL
查看>>
[Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]
查看>>
SaltStack配置管理--状态间的关系(六)
查看>>
Hexo搭建Github静态博客
查看>>
Java集合杂谈
查看>>
[C++] 用Xcode来写C++程序[6] Name visibility
查看>>
[UI] 精美UI界面欣赏[10]
查看>>
音乐波形图动画效果
查看>>
OpenGL投影矩阵(Projection Matrix)构造方法
查看>>
如何提升爬虫的性能
查看>>
回文树/回文自动机(PAM)学习笔记
查看>>
选择器
查看>>
String类的subtring(,)
查看>>
Android 特别大的Activity和Fragment的生命周期图
查看>>
让你的eclipse实现写JAVA代码,HTML,CSS,JAVASCRIPT代码提示
查看>>
Winform dataGridview 为每一个单元格制定一个tooptip
查看>>
BZOJ.2938.[POI2000]病毒(AC自动机)
查看>>
4 —— node —— 启动一个 http 服务器
查看>>