记录一次解决进程阻塞、死锁的过程

之前已经发过两篇文章了,都是关于同一个项目的,之前的两篇文章解决了该项目遇到的两个问题,但还没办法解决现在出现的问题,记录一下解决过程,相信自己很快就能搞定的,哈哈!给自己点自信先!!

前面两篇文章如下:
《怀疑是Tomcat 6.0.24版本问题导致》
《记录一次数据库优化的过程》

《记录一次数据库优化的过程》这一篇中提到系统访问了一段时间后,经常会出现系统速度超慢,打开页面经常会一片空白,之前认为是操作数据库太久,所以优化了存储过程,将速度大大的提升,但今天还是遇到这个问题。

Tomcat进程占了几百个,一直没有消失,而MSSQL也是占用了几百个进程,但这一次发现了几百个进程一直在等待的原因,即系统产生死锁,大部分进程被阻塞,导致一直占用数据库请求,而Tomcat的进程也一直没办法消失。

好了,问题找到了,先暂时结束掉死锁进程先,临时解决这个问题。我们可以通过以下步骤找出死锁进程:

依次打开数据库管理器–管理–活动监视器,如图:

我们可以看到很多进程的状态都是suspended(暂停),等待类型为LCK_M_S(死锁),而后面的阻塞者大部分都是84,即这些进程都被84阻塞了,但这样不能判断就是84的进程产生死锁,我们应该这样看,阻塞者记录的是被哪个进程阻塞,而后面的阻塞则记录该进程阻塞了别人,如上图,可以看到83和84的进程都是1,但84的阻塞者是83,即可以判断83也是被阻塞的,而83才是真正产生死锁的进程。(一句话,那个阻塞者为0,阻塞为1的进程就是产生死锁的进程)

根据上述判断,只需要结束掉83的进程,即可以迅速解决问题。(自己操作了一下,果然就是这样,一结束,搞定)

好了,上述的解决方法只是临时的解决方法,不能从根本解决问题,解决该问题还需要从程序开始分析。

为了解决这个问题,google了很多相关的资料,以下几篇文章可以参考参考:
《快速搞懂 SQL Server 的锁定和阻塞》
《SQLServer事务的隔离级别》
《MSSQL事务开发指南》

从上述文章可以看出,由于SQL Server的「事务隔离级别」默认是READ COMMITTED (已提交读,事务期间别人无法读取),加上SQL Server的锁定造成阻塞时,默认是别的进程必须无限期等待 (LOCK_TIMEOUT = -1)。结果这些大量的客户端 request 无限期等待永远不会提交或回滚的事务,并一直占用着connection pool中的资源,最后造成 connection pooling 连接数目超载。

造成阻塞的原因可能有以下两种:
1)事务:较长的事务,或者事务没有提交或回滚
2)没有建立索引或索引无效,导致全表扫描等等

可能还会有其它原因,暂时先从上面两方面开始排除,接下来先测试是不是事务导致的。

查了整个系统的程序,发现的确有几处打开了事务,也有提交操作,但是在捕获异常的时候没有回滚事务的操作,不知会不会是这个原因,先把这些回滚代码补上去再说。

今晚更新一下程序,再观察几天,如果还有问题,再继续排除其它原因。

————————————————————-
2012.03.19 更新
今天居然还没有出现过之前的情况,莫非真的解决了?再观察几天!哈哈~~

2012.03.20 更新
今天也没有出现问题,继续观察!!

2012.03.21 更新
今天也没有出现问题,继续观察!!

2012.03.29 更新
好吧,问题算解决了,到现在还没有出问题!
以后一定要记得,在程序中使用事务的话,一定要考虑回滚,而且,事务执行的时间要尽量的短!

本文固定链接: http://gevin.me/384.html | Gevin's Blog

该日志由 admin 于2012年03月16日发表在 Database, Java 分类下, 通告目前不可用,你可以至底部留下评论。
原创文章转载请注明: 记录一次解决进程阻塞、死锁的过程 | Gevin's Blog
关键字: ,

记录一次解决进程阻塞、死锁的过程:等您坐沙发呢!

发表评论

快捷键:Ctrl+Enter