读写分离,读写分离死锁解决方案,事务发布死锁解决方案,发布订阅死锁解决方案|事务(进程 ID *)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务

前言:

        由于网站访问压力的问题,综合分析各种因素后结合实际情况,采用数据库读写分离模式来解决当前问题。实际方案中采用“事务发布”模式实现主数据库和只读数据库的同步,其中:

    发布服务器1台:sql2005,推送订阅模式

    订阅服务器2台:sql2005

问题:

        以上方案后实施后,数据同步正常,但从日志中发现了死锁情况。错误提示如:事务(进程 ID *)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

查询一些资料后,确定是数据同步的同时资源被锁,同时用户访问页面请求,导致死锁产生,按照事务优先级,应用程序产生死锁。

解决方法:

        找到大致思路后,查询了一些资料,大部分资料显示是死锁如何产生,如果跟踪日志,然后根据日志优化查询等方向,尝试一些方案后死锁减少,但并没有彻底解决,最后转换思路,从项目实际情况来看,主要是资讯信息的查询,对查询结果的安全性要求相对不高,所以可以接受“脏”数据的情况,在某种情况下又能提升查询的性能,于是在一些查询频繁和数据量比较大的几个表的select语句中加入with(nolock),死锁问题彻底解决。

 

建议:

        处理一个数据库死锁的异常时候,其中一个建议就是使用 NOLOCK 或者 READPAST,对于非银行等严格要求事务的行业,搜索记录中出现或者不出现某条记录,都是在可容忍范围内,所以碰到死锁,应该首先考虑,我们业务逻辑是否能容忍出现或者不出现某些记录,而不是寻求对双方都加锁条件下如何解锁的问题。

NOLOCK 和 READPAST 都是处理查询、插入、删除等操作时候,如何应对锁住的数据记录。但是这时候一定要注意NOLOCK 和 READPAST的局限性,确认你的业务逻辑可以容忍这些记录的出现或者不出现: 
简单来说:

NOLOCK 可能把没有提交事务的数据也显示出来.

READPAST 会把被锁住的行不显示出来 

不使用 NOLOCK 和 READPAST ,在 Select 操作时候则有可能报错误:事务(进程 ID **)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。 

 

做此记录,希望给遇到同样的问题的朋友一些帮助。

posted @ 2018-04-13 19:35  左正  阅读(769)  评论(0编辑  收藏  举报