我正在从MSDN Page about SQL Server lock escalation
读取SQL Server锁定升级我的问题是,似乎锁升级的主要原因是为了减少维护更多锁的开销(例如,当为表获取更多行锁时,行级锁被升级到表级)。我的问题是,维护更多的锁会提高并发性,这是一个好处,为什么它是一个开销?根据我的拙见,锁定应该尽可能小,以通过提高并发性来提高数据库性能。任何人都可以用简单的方式解释为什么需要锁定升级以及所谓的锁定开销是什么?
提前谢谢, 乔治答案 0 :(得分:15)
任何人都可以用简单的方式解释为什么需要锁定升级以及所谓的锁定开销是什么?
当你更新一个表并锁定一行时,你需要以某种方式记录这个事实:这是一行,它已被更新并锁定。
当你更新百万行时,你需要做几百万次,因此有一些空间来保持百万次锁。
SQL Server在内存中保留一个锁列表,而Oracle在表空间中保留。
这可能是因为Oracle已经老了(比我大),而且与Oracle相比,SQL Server很年轻。
从设计师的角度来看,将临时资源(如锁)保存在永久存储中并不是那么明显的解决方案。只需提一点:您可能需要磁盘写入才能执行SELECT FOR UPDATE
。
Oracle的核心功能是在80年代早期开发的,当时将内存保留在内存中根本不是一种选择。他们只是 以某种方式使用磁盘空间。
如果要使用磁盘空间,则必须在磁盘上的某处放置一个锁。
如果不在行本身内的哪一行保持锁定?
SQL Server的锁系统开发人员在发明名为Sybase的RDBMS设计时决定在临时存储(即RAM)中存储临时内容(即锁)。
但Oracle的设计始终是平衡的:如果数据库中有1,000,000行,那么你有1,000,000个锁的存储空间,如果你有10亿行,你可能会存储数十亿个锁等。
从这个意义上说,SQL Server的设计很脆弱,因为你的RAM和硬盘空间可能不平衡。您可以轻松拥有16M的RAM和几TB的磁盘空间。而你的记忆就无法掌握所有的锁。
这就是为什么当锁定计数达到一定限度时,SQL Server决定升级锁定:而不是为数据页面中的10个单独行(需要10条记录)保留锁定,它会锁定整个数据页面(需要1条记录)。
另一方面,Oracle在更新行时只需将锁写入数据页。这就是为什么Oracle的锁是行级的。
Oracle不会以常识的方式“管理”锁定:您不能在Oracle中获取锁定页面列表。
当一个事务需要更新一行时,它只会进入该行并查看它是否被锁定。
如果是,它查看哪个事务持有锁(此信息包含在数据页中的锁描述符中)并将自身添加到该事务的通知队列中:当锁定事务死亡时,原始事务会得到通知并锁定数据。
从并发性的角度来看,锁升级完全是一个穷人的解决方案:它不会增加并发性。比方说,你可以锁定你甚至没有碰过的那一行。
从性能的角度来看,在内存中执行操作当然比在磁盘上执行操作更快。
但是由于Oracle缓存数据块并且无论如何都在内存中执行上述实际操作,因此性能相同或接近它。
答案 1 :(得分:4)
如果SQL Server优化器估计/决定查询将“访问”某个范围内的所有行,那么在该范围内保持单个锁定而不是必须协商许多锁定(锁必须进行类型测试)。这是消耗较少的锁资源(系统范围的资源)的补充。
如果您有一个设计良好的架构,以及适合您的查询工作负载的索引(定期维护),您不必担心正在发生的升级。在许多情况下,可以通过适当的覆盖索引来消除阻塞表锁。
更新:查询的覆盖索引意味着不需要执行对群集的查找,这样可以减少阻止插入表的机会。
答案 2 :(得分:1)
答案 3 :(得分:1)
“有效”的定义很复杂。有时,如果许多进程可以在没有冲突的情况下做到这一点,那么优化并发性会更有效。有时,采用临时并发命中以更快地完成单个进程会更有效。升级后的锁会使其他进程保持不变,因此这个过程可以完成任务并完成任务。
答案 4 :(得分:1)
有关如何维护锁的具体信息,您可以看到Microsoft SQL Server 2005的第8章:存储引擎(我没有附属,这只是我遇到的第一个内部信息)。如果您有一个books24x7帐户,那就在那里。它在一个> 16GB的内存机器上显示锁定哈希表中有2 ^ 25(33554432)个插槽,上限为2 ^ 31个插槽。
对于给定的应用程序,您可以很好地发现仅使用细粒度锁定的总吞吐量更高。正如您可能猜到的,这一切都取决于锁管理的开销与潜在的过度锁定相比如何。