禁用sqlserver的锁升级
锁升级
SQLSERVER、DB2中的锁是内存里面实现的,这就有个资源消耗问题,当锁的数量达到一个阀值或内存有压力时,就会引发锁升级。实际的情况是从row lock直接升级到table lock,而不会小升级到page lock。ORACLE的锁是block里面实现的,行锁是存放在每行的行头里面的,占用一个字节,ORACLE不会发生锁升级。
减少锁升级的方式有以下几种:
禁用sqlserver实例的锁升级
禁用特定表的锁升级
加大阀值,减少锁升级的可能(sp_configure 'locks', 10000; RECONFIGURE;)
启用行版本控制
禁用数据库实例的锁升级
在SQL Server 2005 中,可以使用跟踪标志 1211、1224 来禁用整个实例中的锁升级。
标志1211-完全禁止锁升级,但锁使用的内存会被限制在动态分配内存的60%,当超过这个值时,更多的锁将会伴随着内存溢出错误而失败。
标志1224-禁止锁升级,但内存使用超过40%时,会自动开启锁升级
如果标志1211和1224跟踪标志同时被设置了,只有标志1211会生效。
禁止特定表的锁升级
在SQL Server 2008及更高版本,可以使用新的选择来禁止某个表的锁升级
ALTER TABLE SET (LOCK_ECALATION = AUTO | TABLE | DISABLE)
TABLE: 直接从行锁升级到表锁(此为默认值)
AUTO: 如果存在表分区,则升级为分区锁,但不会进一步升级。
DISABLE:禁用锁升级,这并不意味着禁用表锁(在序列化隔离等级的条件下进行表扫描等操作时还需要表锁)
关于 rowlock
网上很多资料提到,语句中使用rowlock可以强制使用行锁,但实际测试发现没有效果。
查阅资料显示:使用锁定提示如 ROWLOCK 只改变初始锁定计划。锁提示不能防止锁升级。
Using a lock hint such as ROWLOCK only alters the initial lock plan. Lock hints do not prevent lock escalation.