阻塞与死锁是除内存、CPU、IO外另一个影响性能的因素。对OLTP系统尤为严重
一般以下问题是死锁的征兆:
1、 并发用户少的时候,一切正常,但是随着用户数量增多,性能越来越慢。
2、 客户端经常收到以下错误:
Error 1222:Lock request time out period exceeded.(已超过锁请求超时时段)
Error 1205:Your transaction(process ID #XX) was deadlocked on{lock|communication buffer|thread} resources with another process and has beenchosen as the deadlock victim.Rerun your transaction.(事务(进程ID XX)与另一个进程被死锁在XX资源上,并且已被选作死锁牺牲品。请重新运行该事务。)
超时错误:Timeout expired.The timeout period elapsed prior to completion ofthe operation or the server is not responding.
3、 应用程序运行很慢,但是SQL Server 硬盘、CPU利用率很低。运行sp_who命令很快返回。
4、 有些查询能经行,但是有些特定查询或者修改总是不能返回。
5、 重启SQLServer就能解决。但是有可能跑一段时间以后又出现问题。
堵塞和死锁是性能问题,更是设计问题。而不是数据库服务器自身的问题。从根本上解决死锁问题必须从设计本身着手。
在了解死锁和堵塞原因之前,先要了解关系数据库中的一个概念:事务
堵塞和死锁的3大因素:连续持有锁时间过长,数目过多,粒度过大产生的原因。
锁产生的背景:
1、 事务是单个逻辑工作单元执行的一系列操作。必须具有:原子性、一致性、隔离性和持久性(ACID):
l 一致性:事务完成时,数据必须保持一致状态。事务结束时,所有内部数据结构必须都是正确的。
l 隔离性:与其他并发事务所做的修改必须隔离。虽然用户在并发操作,但是事务是串行执行的。
l 持久性:事务完成后,影响是永久的。
l 原子性:事务要么做、要么不做。
2、 从业务逻辑上实现ACID,有两方面:
2.1、程序员要负责启动和结束事务,确定一个事务的范围。并要控制好合适的结束时间。
2.2、SQL Server数据库引擎强制该事务的物理完整性:
2.2.1、锁定资源,使事务保持隔离。
2.2.2、先写入日志方式,保证事务的持久性。
2.2.3、事务管理特性,强制保证事务的原子性和一致性。如果事务完成不了,数据库引擎会撤销所做的操作。
所以,锁是SQLServer实现事务隔离的一部分,阻塞也是事务隔离的体现。是用户使用事务所要付出的代价。开发者和DBA的工作不是去消除阻塞,而是把阻塞时间和范围控制在合理的范围内。完全消除阻塞是不可能的。
为了减少大范围阻塞,建议做到以下几点:
1、 申请资源的互斥度:如果不同的连接申请的锁都是互相兼容的,那么不会产生阻塞。
2、 锁的范围和数目多少:良好的设计可以使申请的锁的粒度和数目控制在最小范围内。
3、 事务持有锁资源的时间长短:对共同所需的锁,持有时间越短越好。