自定义索引的锁定

SQL Server 数据库引擎使用动态锁定策略,这种策略能够在大多数情况下自动为查询选择最佳锁定粒度。建议您不要替代启用页锁定和行锁定的默认锁定级别,除非透彻地了解了表或索引的访问模式且这些访问模式保持一致,并且存在有待解决的资源争用问题。替代锁定级别可以明显妨碍对表或索引的并发访问。例如,对用户时常访问的大型表仅指定表级锁可能会造成瓶颈,因为用户必须等待表级锁释放后才能访问该表。

在为数不多的情况下,不允许页锁定或行锁定可能会有好处,但必须透彻地了解访问模式且这些访问模式保持一致。例如,某个数据库应用程序使用的查找表在批处理进程中每周更新一次。并发读取器使用共享锁 (S) 访问表,每周批处理更新使用独占锁 (X) 访问表。关闭表的页锁定和行锁定可以使读取器通过共享表锁对表进行并发访问,从而在整周内降低锁定开销。在批处理作业运行时,由于它获得了独占表锁,因此可以高效地完成更新。

由于每周批处理更新在运行时将阻止并发读取器访问表,因此关闭页锁定和行锁定可能是可取的,也可能不可取。如果批处理作业仅更改少数几行或几页,则可以更改锁定级别以允许行级别或页级别的锁定,这将允许其他会话读取表中的数据而不会受到阻止。如果批处理作业要进行大量更新,则获取表的独占锁可能是确保批处理作业高效完成的最佳途径。

当两个并发操作获得同一个表的行锁然后进行阻止时,偶尔会出现死锁,因为这两个操作都需要锁定该页。如果不允许使用行锁,则会强行使其中一个操作等待,从而避免死锁。

可以使用 CREATE INDEX 和 ALTER INDEX 语句来设置索引使用的锁定粒度。该锁设置适用于索引页和表页。另外,CREATE TABLE 和 ALTER TABLE 语句还可用于设置 PRIMARY KEY 和 UNIQUE 约束的锁定粒度。为了向后兼容,还可以使用 sp_indexoption 系统存储过程设置粒度。若要显示给定索引的当前锁定选项,请使用 INDEXPROPERTY 函数。可以禁止将页级别的锁、行级别的锁或二者的组合用于指定的索引。

禁止的锁

访问索引的锁

页级别

行级别的锁和表级别的锁

行级别

页级别的锁和表级别的锁

页级别和行级别

表级别的锁