@H_502_1@在sql Server的sys.dm_os_memory_cache_entries中,可以查看缓存中条目的原始开销以及缓存条目的当前开销(分别为original_cost和current_cost). DMV sys.dm_os_buffer_descriptors包含当前在内存中的页面的记录以及有关页面的一些元数据. DVM中没有的一个有趣的信息块是数据页的LRU-K值.
解决方法
事实上,就我所见,实际上没有有用的方法可以做到这一点.
另一个答案提到了DBCC PAGE,并让读者了解细节.从实验中我认为它们意味着bUse1.
这没有考虑到DBCC PAGE本身就是对页面的使用,并且在向我们显示之前值会更新.
演示此内容的脚本如下(运行需要12秒).
USE tempdb; CREATE TABLE T(X INT); INSERT INTO T VALUES(1); DECLARE @DBCCPAGE NVARCHAR(100); SELECT @DBCCPAGE = 'DBCC PAGE(0,' + CAST(file_id AS VARCHAR) + ',' + CAST(page_id AS VARCHAR) + ',0) WITH TABLERESULTS;' FROM T CROSS APPLY sys.fn_PhysLocCracker (%%physloc%%) DECLARE @DbccResults TABLE ( ID INT IDENTITY,ParentObject VARCHAR(1000)NULL,Object VARCHAR(4000)NULL,Field VARCHAR(1000)NULL,ObjectValue VARCHAR(MAX)NULL ) INSERT INTO @DbccResults EXEC(@DBCCPAGE) WAITFOR DELAY '00:00:07' INSERT INTO @DbccResults EXEC(@DBCCPAGE) WAITFOR DELAY '00:00:05' INSERT INTO @DbccResults EXEC(@DBCCPAGE) SELECT * FROM @DbccResults WHERE Field = 'bUse1' ORDER BY ID EXEC(@DBCCPAGE) DROP TABLE T
典型的结果是
+----+--------------+-------------------------+-------+-------------+ | ID | ParentObject | Object | Field | ObjectValue | +----+--------------+-------------------------+-------+-------------+ | 8 | BUFFER: | BUF @0x00000002FE1F1440 | bUse1 | 54938 | | 49 | BUFFER: | BUF @0x00000002FE1F1440 | bUse1 | 54945 | | 90 | BUFFER: | BUF @0x00000002FE1F1440 | bUse1 | 54950 | +----+--------------+-------------------------+-------+-------------+
第二个结果是
+---------+-------------------------+--------------+--------------------+ | BUFFER: | BUF @0x00000002FE1F1440 | bpage | 0x00000002F4968000 | | BUFFER: | BUF @0x00000002FE1F1440 | bhash | 0x0000000000000000 | | BUFFER: | BUF @0x00000002FE1F1440 | bpageno | (1:120) | | BUFFER: | BUF @0x00000002FE1F1440 | bdbid | 8 | | BUFFER: | BUF @0x00000002FE1F1440 | breferences | 0 | | BUFFER: | BUF @0x00000002FE1F1440 | bcputicks | 0 | | BUFFER: | BUF @0x00000002FE1F1440 | bsampleCount | 0 | | BUFFER: | BUF @0x00000002FE1F1440 | bUse1 | 54950 | | BUFFER: | BUF @0x00000002FE1F1440 | bstat | 0x9 | | BUFFER: | BUF @0x00000002FE1F1440 | blog | 0x1c9a | | BUFFER: | BUF @0x00000002FE1F1440 | bnext | 0x0000000000000000 | +---------+-------------------------+--------------+--------------------+
所以很明显,这些LRU值是自某个时代以来的秒数.重新启动sql Server服务不会改变纪元,但会重新启动计算机.
该值每65,536秒滚动一次,所以我认为它只是使用类似system_up_time mod 65536的东西
这确实留下了一个未解决的问题(任何参与者?).根据内部书籍,sql Server使用K = 2的LRU-K.不应该有bUse2吗?如果是这样的话呢?
有一种观察bUse1值而不改变它的方法虽然我知道,这里是demonstrated by Bob Ward.
将调试器附加到sql Server进程并显示缓冲区结构的内存地址的引用内存(上面显示为0x00000002FE1F1440).
我在运行上面的脚本后立即执行了此操作,并看到以下内容.
(从之前的实验中我发现突出显示的字节是在运行之间唯一改变的字节,所以这些肯定是正确的).
一个令人惊讶的方面是SELECT CAST(0xc896 as int)= 51350.
这比DBCC PAGE报告的要少3600(一小时).
我相信这是尝试通过调用DBCC PAGE本身来拒绝保存在缓存中的页面.对于“正常”页面,选择此一小时调整不会发生.跑完之后
SELECT * FROM T SELECT ((ms_ticks) % 65536000) / 1000 AS [Roughly Expected Value] FROM sys.dm_os_sys_info
内存中显示的值与预期一致.
DBCC命令实际上两次更新该值.一旦到了
sqlmin.dll!BPool::Touch() + 0x3bfe bytes sqlmin.dll!BPool::Get() + 0x12e bytes sqlmin.dll!LatchedBuf::ReadLatch() + 0x14f bytes sqlmin.dll!UtilDbccDumpPage() + 0x364 bytes sqlmin.dll!DbccPage() + 0xfa bytes sqllang.dll!DbccCommand::Execute() + 0x153 bytes
随着更高的价值,然后再次
sqlmin.dll!LatchedBuf::FreeAndUnlatch() + 0x71 bytes sqlmin.dll!UtilDbccDumpPage() + 0x545 bytes sqlmin.dll!DbccPage() + 0xfa bytes sqllang.dll!DbccCommand::Execute() + 0x153 bytes
用较低的一个.
我不知道如何在不使用DBCC BUFFER / DBCC PAGE的情况下获取页面的缓冲区地址,并且使用这两个更改我们要检查的值!