Sql-Server

記憶體問題:Tempdb 使用了幾乎所有的緩衝區記憶體

  • November 30, 2018

在我今天工作的一台伺服器上,我看到幾乎所有的緩衝區記憶體都由 tempdb 填充。因此,伺服器上的記憶體非常低。

中央處理器 在此處輸入圖像描述

臨時數據庫:

在此處輸入圖像描述

版本:

Microsoft SQL Server 2014 (SP2-CU13) (KB4456287) - 12.0.5590.1 (X64)

2018 年 8 月 1 日 01:23:36 版權所有 (c) Microsoft Corporation Standard Edition (64-bit) o​​n Windows NT 6.3 (Build 14393:) (管理程序)

4 個數據文件 = 4096 MB 1 個日誌文件 = 1536MB

我的問題是 TEMPDB 使用了 13GB 的緩衝區記憶體。我檢查了 tempdb 中的對象,我的 sp_blitz 臨時表所在的最大對象,其中沒有那麼大。

沒有為任何數據庫啟用 RCSI,因此不應該是版本儲存問題。

沒有未結交易

沒有打開的游標。

當我在 tempdb 上執行檢查點時,大約需要 30 秒,但完成。

當我執行 dbcc dropcleanbuffers 時,緩衝區記憶體中 tempdb 的存在會減少 tto 有時 1 GB 有時 4 GB 30 秒後它又恢復了 13 GB 的輝煌

例如:

dbcc dropcleanbuffers


DECLARE @total_buffer INT;

SELECT @total_buffer = cntr_value
FROM sys.dm_os_performance_counters 
WHERE RTRIM([object_name]) LIKE '%Buffer Manager'
AND counter_name = 'Database Pages';

;WITH src AS
(
SELECT 
database_id, db_buffer_pages = COUNT_BIG(*)
FROM sys.dm_os_buffer_descriptors
--WHERE database_id BETWEEN 5 AND 32766
GROUP BY database_id
)
SELECT
[db_name] = CASE [database_id] WHEN 32767 
THEN 'Resource DB' 
ELSE DB_NAME([database_id]) END,
db_buffer_pages,
db_buffer_MB = db_buffer_pages / 128,
db_buffer_percent = CONVERT(DECIMAL(6,3), 
db_buffer_pages * 100.0 / @total_buffer)
FROM src
ORDER BY db_buffer_MB DESC; 

緊隨其後的結果:

db_name db_buffer_pages db_buffer_MB    db_buffer_percent
tempdb  620627  4848    58.096

30 秒後:

db_name db_buffer_pages db_buffer_MB    db_buffer_percent
tempdb  1313835 10264   83.560

Tempdb 緩衝區記憶體使用高峰期 (its_over_9000.jpeg) 在此處輸入圖像描述

檢查 tempdb 中的對象:

use tempdb 

go
SELECT 
   t.NAME AS TableName,
   s.Name AS SchemaName,
   p.rows AS RowCounts,
   SUM(a.total_pages) * 8 AS TotalSpaceKB, 
   SUM(a.used_pages) * 8 AS UsedSpaceKB, 
   (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables t
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
GROUP BY  t.Name, s.Name, p.Rows
ORDER BY  TotalSpaceKB desc

前 4 個值:

TableName   SchemaName  RowCounts   TotalSpaceKB    UsedSpaceKB UnusedSpaceKB
#A3B2C869   dbo 0   72  16  56
#A52E4149   dbo 0   72  16  56
#A59B10DB   dbo 0   72  16  56
#A68F3514   dbo 0   72  16  56

總共有 74 個對象。

我確實看到很多(375 000+ !!!)頁有 7965 字節的可用空間,而我的記憶體緩衝區中只有一行。使用的查詢:

select * from sys.dm_os_buffer_descriptors
where database_id = 2
order by free_space_in_bytes desc 

例如

file_id page_id page_level  allocation_unit_id  page_type   row_count   free_space_in_bytes
1   109763  0   71635384526569472   INDEX_PAGE  1   7965

但更多的是 40 字節的可用空間 (1M),請參見下文。

過濾更多:

select page_type,free_space_in_bytes,  count(*)as counter from sys.dm_os_buffer_descriptors
where database_id = 2
group by page_type, free_space_in_bytes
having count(*) > 500
order by free_space_in_bytes desc 

在此處輸入圖像描述

問題

為什麼在發出 dbcc dropcleanbuffers 後我的 tempdb 會很快填滿?我錯過了什麼,我應該檢查什麼?

2018 年 11 月 30 日更新

將 TEMPDB 設置為 4 個 512 MB 的文件並重新啟動伺服器後,緩衝區中的 MB 似乎較低。但是它仍然是6GB。

在此處輸入圖像描述

關於現在做什麼/檢查的任何其他想法?

額外的資訊:

跟踪狀態

在此處輸入圖像描述

探查器擷取的不斷執行的查詢範例:

exec sp_reset_connection 

SELECT COUNT(*) FROM dbo.SomeTable WHERE Error IS NULL

一些連接使用可序列化:

-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level serializable 

有些沒有

-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

Max mem 有點偏低:

在此處輸入圖像描述

DBCC 頁面檢查:DBCC TRACEON (3604);

DBCC 頁面 (2, 5, 474258, 3); DBCC TRACEOFF (3604);

bpage = 0x00000016AA16C000          bhash = 0x0000000000000000          bpageno = (5:474258)
bdbid = 2                           breferences = 0                     bcputicks = 0
bsampleCount = 0                    bUse1 = 1952                        bstat = 0x109
blog = 0xcdcdcdcd                   bnext = 0x0000000000000000          

PAGE HEADER:


Page @0x00000016AA16C000

m_pageId = (5:474258)               m_headerVersion = 1                 m_type = 3
m_typeFlagBits = 0x0                m_level = 0                         m_flagBits = 0x8020
m_objId (AllocUnitId.idObj) = -1778255884                                m_indexId (AllocUnitId.idInd) = 255
Metadata: AllocUnitId = 71941054260314112                                Metadata: PartitionId = 0
Metadata: IndexId = -1              Metadata: ObjectId = 0              m_prevPage = (0:0)
m_nextPage = (0:0)                  pminlen = 0                         m_slotCnt = 1
m_freeCnt = 40                      m_freeData = 8150                   m_reservedCnt = 0
m_lsn = (5148:180860:473)           m_xactReserved = 0                  m_xdesId = (0:0)
m_ghostRecCnt = 0                   m_tornBits = 0                      DB Frag ID = 1

Allocation Status

GAM (5:2) = NOT ALLOCATED           SGAM (5:3) = NOT ALLOCATED          PFS (5:469104) = 0x4 100_PCT_FULL
DIFF (5:6) = NOT CHANGED            ML (5:7) = NOT MIN_LOGGED           


Blob row at: Page (5:474258) Slot 0 Length: 8054 Type: 3 (DATA)

Blob Id:2794796220416



000000464FAFA06E:  0044002b  006f0051  00550038  00520058 +.D.Q.o.8.U.X.R.
...

@Craig 你的輸出:

在此處輸入圖像描述 在此處輸入圖像描述 在此處輸入圖像描述 在此處輸入圖像描述

不確定,但sys.allocation_units和 sys.partitions 之間的連接並不完全正確。例如

select bd.file_id, bd.page_id, p.*
from sys.dm_os_buffer_descriptors bd
left join sys.allocation_units au
on bd.allocation_unit_id = au.allocation_unit_id
left join sys.partitions p
 on ( au.type in (1,3) and au.container_id = p.hobt_id )
   or
    ( au.type = 2 and au.container_id = p.partition_id )
where database_id = 2

您還可以嘗試檢查Tempdb 中的一些頁面,以查看頁眉和數據是否為您提供了它們來自何處的任何指示。

你能試試這個查詢並發送輸出嗎?

SET NOCOUNT ON;

SELECT
(DATEDIFF(n, dtat.transaction_begin_time, GETDATE())) as duration, *
FROM 
sys.dm_tran_active_transactions dtat 
INNER JOIN sys.dm_tran_session_transactions dtst 
ON dtat.transaction_id = dtst.transaction_id
INNER JOIN sys.dm_exec_sessions es 
ON dtst.session_id = es.session_id
WHERE es.session_id > 50 

謝謝,

克雷格

引用自:https://dba.stackexchange.com/questions/223220