问题描述
整个程序就两个业务处理,如下:(1)一个纯查询业务:QueryData(){多个表查询操作······}(2)一个数据更新业务:publicstaticAutoResetEventmEvent=newAutoResetEvent(true);//静态的全局事件对象,用于事务并发同步控制,保证任一时刻只有一个事务得到执行。UpdateData(){//数据更新业务mEvent.WaitOne();//等待信号SqlTransactiontran=BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);//启用事务,并把隔离级别设置为未提交读,即允许脏读,目的是使查询业务不被阻塞。SqlCommanddbCommand=null;dbCommand=newSqlCommand(sSQL,m_Connect);dbCommand.Transaction=m_tran;//使用事务执行各种更新操作······mEvent.Set();//释放事件}(3)运行过程还是出现了死锁:用profier捕捉发现,当同时有一个客户端执行数据更新业务UpdateData、五个客户端执行查询业务QueryData的情况下会出现事务死锁。问题:(1)整个程序就只有一个事务,何来的事务争用资源导致死锁?难道查询业务也自动变成了事务?(2)就算查询业务自动变成了事务,那么,更新业务中事务隔离级别设置为脏读,难道这个设置不起作用?请高手指点,万分感谢!
解决方案
解决方案二:
对于这问题你列出的这些代码显然无法说明任何问题,更新使用的是排他锁,查询使用的是共享锁,排他锁是无法和其他锁共存,那么当你的查询无法正常完成并释放共享锁时,你的update就无法申请到排它锁。但死锁的问题并不一定是查询的共享锁导致,所以这么点代码是很难说明问题的
解决方案三:
允许脏读么直接在sql里写with(nolock),你居然用事务
解决方案四:
你这五个客户端是跨进程了吧,存在于不同机器的不同进程?AutoResetEvent同步事件无法用于跨进程的进程同步,所以死锁了,我猜是这样
解决方案五:
涉及到的表是否都有主键?update的时候是否会更新主键涉及到的列?这些都可能导致select时死锁。如版主所说,允许脏读的话查询时时加上with(nolock)就好。select....from...with(nolock)where....
解决方案六:
非常感谢大家!我这个是网站项目,事件对象是全局的。目前也没有其他办法了,先试试版主的办法看看。