不允许启动新事务,因为有其他线程正在该会话中运行(ef并发错误处理之一)
2013-08-14 10:35
453 查看
最近项目上线试运行过程中,总是遇到各种莫名其妙的问题,纠结了很久,今天就ef出现的“不允许启动新事务,因为有其他线程正在该会话中运行”这个错误,记录自己的解决方法。
当遇到这个问题的时候,在网上搜了很久,在这里还是要鄙视一下那些转载又不写出处的站长。
问题发现:
开始一直以为是数据库或者服务器的问题,因为用的是虚拟空间,很多设置没有办法改变。后来加入站长统计之后,发现pv量居然在200左右,突然意识到有可能是并发造成的。于是自己写了一段测试代码,该段代码的作用是模拟用户阅读新闻的时候,使新闻的阅读次数加1(只是改变字段的值,而不是新增一条浏览记录再去统计阅读次数)。代码如下:
F10跟踪代码运行就报以下错误:
于是监控以下代码发现并发产生的时候,第一次是Modified,第二次却是Unchanged,所以当运行第二次更新的时候,则报错“不允许启动新事务,因为有其他线程正在该会话中运行”
所以最后解决此问题的方法就是将Update的代码改成:
虽然这样解决可以保证程序的稳定性,但是当并发发生的时候,阅读次数就不能+1了。不过阅读次数这个属性对于网站的数据而言并不是很重要,所以先这么解决着吧。如果是比较重要的属性,建议还是通过add方法去增加记录,而不是修改记录。或者通过用存储过程,将数据重新刷进表中,但是这样就缺乏实时性。
真是蛋痛的并发!以后再想想,看看有没有其他的解决办法吧。
当遇到这个问题的时候,在网上搜了很久,在这里还是要鄙视一下那些转载又不写出处的站长。
问题发现:
开始一直以为是数据库或者服务器的问题,因为用的是虚拟空间,很多设置没有办法改变。后来加入站长统计之后,发现pv量居然在200左右,突然意识到有可能是并发造成的。于是自己写了一段测试代码,该段代码的作用是模拟用户阅读新闻的时候,使新闻的阅读次数加1(只是改变字段的值,而不是新增一条浏览记录再去统计阅读次数)。代码如下:
public partial class WebForm1 : System.Web.UI.Page { delegate bool MyDelegate(Read info); protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { ReadInfo ri = new ReadInfo (); Read rad1 = ri.Get(1); rad1.ReadTime += 1; Read rad2 = ri.Get(1); rad2.ReadTime += 1; MyDelegate myDelegate = new MyDelegate(ri.Update); myDelegate.BeginInvoke(rad1, null, null); myDelegate.BeginInvoke(rad2, null, null); Thread.Sleep(300); } } } public class ReadInfo { testEntities mytest = new testEntities(); public ReadInfo() { mytest.Read.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges; mytest.Read.EnablePlanCaching = false; } public Read Get(int Id) { return mytest.Read.SingleOrDefault(c => c.myId == Id); } public bool Update(Read Info) { int Result = 0; if (mytest.Read.Count(c => c.myId == Info.myId) == 1) { Thread.Sleep(100); Result = mytest.SaveChanges(); } return Result > 0; } }
F10跟踪代码运行就报以下错误:
于是监控以下代码发现并发产生的时候,第一次是Modified,第二次却是Unchanged,所以当运行第二次更新的时候,则报错“不允许启动新事务,因为有其他线程正在该会话中运行”
所以最后解决此问题的方法就是将Update的代码改成:
public bool Update(Read Info) { int Result = 0; if (mytest.Read.Count(c => c.myId == Info.myId) == 1) { if (Info.EntityState == System.Data.EntityState.Modified) { mytest.Refresh(RefreshMode.ClientWins, Info); Thread.Sleep(100); Result = mytest.SaveChanges(); } } return Result > 0; }
虽然这样解决可以保证程序的稳定性,但是当并发发生的时候,阅读次数就不能+1了。不过阅读次数这个属性对于网站的数据而言并不是很重要,所以先这么解决着吧。如果是比较重要的属性,建议还是通过add方法去增加记录,而不是修改记录。或者通过用存储过程,将数据重新刷进表中,但是这样就缺乏实时性。
真是蛋痛的并发!以后再想想,看看有没有其他的解决办法吧。
相关文章推荐
- asp.net MVC + linq to entity报"不允许启动新事务,因为有其他线程正在该会话中运行."错误解决方法
- MVC3"不允许启动新事务,因为有其他线程正在该会话中运行"错误解决方法
- EF 不允许启动新事务,因为有其他线程正在该会话中运行。
- entity异常 不允许启动新事务,因为有其他线程正在该会话中运行。
- 不允许启动新事务,因为有其他线程正在该会话中运行。
- "无法启动程序,因为计算机中丢失*.dll” 运行exe错误解决方法
- ORACLE DML LOCK时找出对应SESSION正在执行的SQL语句(ORA-12841,无法变更事务处理中的会话并行 DML 状态)
- java并发:中断一个正在运行的线程
- IIS7.5 HTTP错误403.1-Forbidden 您尝试从某个目录运行CGI、ISAPI或其他可执行程序,但该目录不允许运行可执行文件
- SQLServer2005触发器提示其他会话正在使用事务的上下文的解决方法
- SQLServer出现 '其他会话正在使用事务的上下文' 的问题原因?
- JAVA多线程—CountDownLatch-一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
- 饥饿和公平 原文地址 By Jakob Jenkov 翻译 Simon-SZ 校对:方腾飞 如果一个线程因为CPU时间全部被其他线程抢走而得不到CPU运行时间,这种状态被称之为“饥饿”。而该线
- (转载)使用ADOConnet.BeginTrans后,出现错误提示:无法在此会话中启动更多的事务?
- 运行错误:应用程序无法启动因为并行配置不正确。the application has failed to start because its side-by-side configuration is incorrect 解决方法
- APP-FND-00204:并发管理器在运行并发请求xxxxx的派生并发程序 接收事务处理管理器 - RCVOLTM时出错。TM-TIMEOUT.
- 解决任务计划程序未启动任务,因为相同任务的实例正在运行的问题
- CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
- SQLServer2005触发器提示其他会话正在使用事务的上下文的解决方法
- 结论: blocking_query 是当前堵塞其他会话正在运行的SQL.而不是原始堵塞SQL