На самом деле, насколько я понимаю, нет никакого полезного способа сделать это.
В другом ответе упоминается, 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 |
+---------+-------------------------+--------------+--------------------+
Выход после 7-секундной задержки увеличивается на 7, а после 5-секундной задержки на 5.
Таким образом, кажется очевидным, что эти значения LRU являются секундами с некоторой эпохи. Перезапуск службы SQL Server не меняет эпоху, но перезапускает машину.
Значение переворачивается каждые 65 536 секунд, поэтому я предполагаю, что оно просто использует что-то вроде system_up_time mod 65536
Это оставляет один вопрос без ответа в моем уме (любые берущие?). SQL Server использует LRU-K
с K=2
согласно внутренним книгам. Там не должно быть bUse2
? Если так, то где это?
bUse1
Хотя есть один способ наблюдать значение, не меняя его, о котором я знаю, и это продемонстрировал Боб Уорд здесь.
Присоедините отладчик к процессу SQL Server и отобразите в памяти ссылки для адреса памяти структуры буфера (показано 0x00000002FE1F1440
выше).
Я сделал это сразу после запуска сценария выше и увидел следующее.
(Из предыдущих экспериментов я обнаружил, что выделенные байты были единственными, которые менялись между прогонами, так что они определенно правильные).
Одним удивительным аспектом является то, что SELECT CAST(0xc896 as int)
= 51350
.
Это ровно на 3600 (один час) меньше, чем сообщалось DBCC PAGE
.
Я считаю, что это попытка отрицать страницы, хранящиеся в кеше, вызывая 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
каким-либо образом, и используя оба эти изменения, значение, которое мы пытаемся проверить!