我有点好奇,具有 128 GB 数据库 RAM 大小的 SQL 2012 企业版之一是 370 GB 并且还在增长,锁 (OBJECTSTORE_LOCK_Manager) 内存管理员使用的内存量显示为 7466016 KB。我还可以通过查看 perf counter 来确认select * from sys.dm_os_performance_counters where counter_name = 'Lock Memory (KB)'
但是,当我运行查询
select count(*) from sys.dm_tran_locks
它仅显示 16 个锁。那么什么是使用超过 7 GB 的锁。有没有办法找出来?
这是否意味着一旦为锁分配了内存,SQL 还没有释放它?在过去的 1 小时内,我没有看到超过 500 的锁计数,但锁内存保持不变。
最大服务器内存为 106 GB,我们不使用内存中的锁定页面,并且在过去 12 小时内我没有看到任何内存压力或错误日志中的任何错误。可用 MBytes 计数器显示超过 15 GB 的可用内存。
活动监视器始终显示 0 个等待任务,因此显然没有阻塞。
考虑到 SQL 服务器锁需要大约 100 字节的内存 7 GB 是很多内存并试图找出谁在使用它。
我运行服务器仪表板按锁计数报告顶级事务,它说“当前系统上没有运行任何锁定事务。但是,锁内存仍然如上所述显示。数据库在夜间最忙。
锁管理器是一个超级热的关键代码路径(可能是最热的关键代码路径),如果它必须等待每个锁性能的内存分配,它就会崩溃。它可能会分配大内存块并自行管理它们。如果它还保留内存以便它不会在某些关键代码路径中耗尽内存,我不会感到惊讶。
@RemusRusanu 答案的附录(不适合发表评论)...
鉴于数据库引擎在升级之前将允许每个对象最多 5000 个锁,并考虑到 Remus 关于锁管理器的关键性质的回答,高预留开始看起来是合理的:
5000(锁)* 10(表或索引)* 96(每个锁的字节数)* 1000(并发查询)= 4.47GB
我推测保留是由可用 RAM 和当前工作负载的组合得出的,但在任何地方都没有看到它的文档或博客。还可以推测,您的 128GB 内存在 2008 年会被认为是慷慨的,而 7GB 的预留表明预计该大小的 OLTP 工作负载会很重。
sys.dm_tran_lock 显示锁定的资源和锁定资源的请求,而不是锁定的单个行。每个锁定的资源将包含许多行,并且可能还有其他对象,被锁定。