全文地址:
SQL2005中的事务与锁定(七)
SQL2005中的事务与锁定(七)
6、锁升级 禁止升级
锁定粒度是一个查询或更新所锁定的最小数据,粒度不同数据库的性能和并发能力是此消彼长的,怎么来理解呢?锁定的粒度越小并发的用户数越多,这是显而易的,如果这时发生一种情况,根据业务规律要锁定大量的记录行来进行更新,在保持并发用户的前提下,我们锁定的记录的行锁或键锁就很多,我们知道锁定不是免费的午餐,是要付出代价的,管理的锁定多越多系统资源开销就越大。还记得我们在前面介绍过锁块吧,锁块是一个64/128(128是64位操作系统)字节的内存块,另外对每一个申请或正持有锁块的进程还要准备一个32/64(64是64位操作系统)字节的内存块来描述这些进程,在这儿我们确定一个前提:不管锁定粒度的大小,每一个锁定都占用几乎同样的系统开销。好,比如我们要进行10W行数据更新,为了并发我们都采用行锁来锁定,按照锁块的定义那么我们就得需要64B * 100000+N*32B= 6400000B +32NB(理论更新我们取N=1相对于6400000可以忽略)> 6.4M的RAM来管理这些行锁,假设并发进程(当然是不同资源上的)数量是X,那么当前数据库就得要X*6.4M的RAM用于管理锁定,显然这种对RAM需求的上升是系统无法忍受,不可能无限制的满足的这种增长,那么SQLSERVER得用一种办法来防止系统使用太多的内存来追踪锁定并且提高锁定的效率。这个任务交给了锁管理器,它负责平衡资源的使用(当然还负责从特定操作的开始到结束保持连续、逻辑完整性),这时管理器就采取锁定升级这一明智造择,从行锁或键锁或页锁升级为表级锁定,比较6.4M和96B,显然获取一个表级锁定比持有许多行或键锁更有意义。
锁升级的意义是显而易见,使得锁定开销下降并避免系统资源耗尽。在结构引擎里我们提及锁管理器,系统分配给锁管理器的内存是有限的,锁的升级保证了锁定占用内存维持一个合理的限度。
锁升级发生的时机:
1、在一个对象上一个查询或更新持有锁的数量超过阀值。SQL2005缺省是5000个锁(记得SQL6.0只有200个,但是我们要记住SQL6.0只有页面锁定哦)。
2、锁资源占用的内存超过AWE或常规内存的40%,40%是一个约数。
时机一满足SQLSERVER就会尝试锁升级,当然升级不一定会成功,当失败后在同一个对象上的锁资源再次上升到一定程度时升级会再次发生,如果升级成功SQLSERVER会释放对象上先前获得的行、键、分页锁定。升级失败发生当另外一个进程对表有行或页有排它锁定时。
锁升级潜在的危险:
1、锁升级的结果一定是一个完全表级锁定,也就是不可能出现行锁升级为页锁的,最细的行级锁升级的直接结果一定是表锁定。
2、锁升级可能造成意外的阻塞(这个应该是很好理解的)
3、锁升级成功后无法降级
禁止升级 我们知道锁升级是有潜在的危险,并且这种升级的结果是不可能现降级除非事务结束。所以升级不是对所有的应用都是一件好事,MS提供了两个开关项:1211和1224,我们可以通过设置跟踪标识来禁止升级。
7、行锁、页锁
....
...
...