为什么在 table 上使用锁定模式页面

Why use lock mode page on a table

我想知道为什么我需要在 table 上使用锁定模式页面。

最近我想出了一个很好的例子来说明为什么不这样做。当我试图在 table 上插入一行时,出现了死锁。经过大量调查,我发现 table 的锁定级别是 Page,这才是导致死锁的真正原因。

我的猜测是,这是多个应用程序访问同一个数据库的大规模高性能环境中的常见情况

我唯一发现的是,如果我按照与分页发生的顺序相同的顺序处理行,我应该使用页面锁定。这看起来像是一个很少能满足的弱条件(特别是对于可能使这种情况过时的缩放)。

我明白为什么要锁定完整 table 或使用每行锁定,但页面锁定没有多大意义。或者是吗?

您永远不需要在 table 上使用锁定模式页面,但您可以选择这样做。

如果只有一行适合一页(或者一行需要不止一页),它不会造成任何损害。

但是,如果您可以在一个页面上容纳多行,则您可以在 LOCK MODE PAGE 和 LOCK MODE ROW 之间进行有意义的选择。显然,如果您使用 LOCK MODE ROW,那么一个进程在页面的一行上锁定这一事实不会阻止另一个进程在同一页上的不同行上获得锁定,而 LOCK MODE PAGE 会阻止.

LOCK MODE PAGE 的优点是,当单个进程在单个事务中更新页面上的多行时,它需要的锁较少。

因此,您必须采取平衡措施。您可以认为数据库中的行太多,以至于两个进程需要锁定同一页上不同行的机会可以忽略不计,并且使用 LOCK MODE PAGE 知道进程阻塞的风险很小如果您使用 LOCK MODE ROW,则不会阻止其他进程。或者,您可以认为这种阻塞的风险是unacceptable,增加的锁数也不是问题,因此决定无论如何都使用LOCK MODE ROW。

从历史上看,当锁的数量因为内存不足而成为问题时(在大型机器的主内存不到 100 MiB 的日子里!),使用 LOCK MODE PAGE 保存锁比它更有意义现在当系统有几千兆字节的主内存时。

请注意,如果两个进程要更新同一行,使用哪种锁定模式并不重要;一个将获得锁并阻止另一个,直到事务提交(或者如果您不使用显式事务,则直到语句完成)。

请注意,默认锁定模式仍然是 LOCK MODE PAGE,主要是为了尊重历史上一直如此的情况。但是,有一个 ONCONFIG 参数 DEF_TABLE_LOCKMODE,您可以将其设置为 row(而不是 page),这会将默认的 table 锁定模式设置为 LOCK MODE ROW。您仍然可以在 DDL 语句中显式覆盖它,但是如果您没有指定显式锁定模式,则默认值将是 rowpage,具体取决于 DEF_TABLE_LOCKMODE 的设置。