Ala*_*her 10 memory graph sql-server-2019 memory-manager
我目前正在努力升级到 SQL Server 2019,以便利用其中可用的图形功能。我们的数据库存储文件及其子文件的记录,图形特征使我们能够快速找到文件在任一方向的所有关系。我们当前的开发环境在 Linux 服务器上使用 SQL Server 2019 Standard (15.0.4023.6)。
我在运行图形查询时注意到一个令人担忧的问题。服务器的“内部”资源池在图形查询后似乎没有释放所有资源。如果不选中,这会填满资源池。在重新启动 SQL Server 进程之前,较大的查询将失败。根据服务器负载,这可能会在短短 1-2 小时内发生。这也会填满 tempdb 并威胁填满存储驱动器。在服务器重新启动之前,tempdb 的文件也不能显着缩小/截断。在配置中,'memory.memorylimitmb'没有设置,所以当资源池开始使用默认80%的系统内存(12.8GB,16GB系统内存)中的大部分时,就会出现这个问题
要在演示数据库中设置表:
CREATE TABLE FileNode (ID BIGINT NOT NULL CONSTRAINT PK_FileNode PRIMARY KEY) AS NODE
GO
CREATE TABLE FileNodeArchiveEdge AS EDGE
GO
CREATE INDEX [IX_FileNodeArchiveEdge_ChildFile] ON [dbo].[FileNodeArchiveEdge] ($from_id)
GO
CREATE INDEX [IX_FileNodeArchiveEdge_ParentFile] ON [dbo].[FileNodeArchiveEdge] ($to_id)
GO
Run Code Online (Sandbox Code Playgroud)
填充演示数据库表:
INSERT INTO [FileNode] (ID) VALUES
(1),(2),(3),(4),(5),
(6),(7),(8),(9),(10),
(11),(12),(13),(14),(15)
-- Convenient intermediate table
DECLARE @bridge TABLE (f BIGINT, t BIGINT)
INSERT INTO @bridge (f, t) VALUES
(1,4),
(4,9),
(4,10),
(1,5),
(5,11),
(11,12),
(2,5),
(2,6),
(6,13),
(6,14),
(13,15),
(14,15),
(15,12),
(7,14),
(3,7),
(3,8)
INSERT INTO FileNodeArchiveEdge
($from_id, $to_id)
SELECT
(SELECT $node_id FROM FileNode WHERE ID = f),
(SELECT $node_id FROM FileNode WHERE ID = t)
FROM @bridge
Run Code Online (Sandbox Code Playgroud)
要获取文件的所有子 ID(重复相同的查询将占用内存资源并导致“USERSTORE_SCHEMAMGR”无法控制地增长):
DECLARE @parentId BIGINT = 1
SELECT
LAST_VALUE(f2.ID) WITHIN GROUP (GRAPH PATH)
FROM
FileNode f1,
FileNodeArchiveEdge FOR PATH contains_file,
FileNode FOR PATH f2
WHERE
f1.ID = @parentId
AND MATCH(SHORTEST_PATH(f1(-(contains_file)->f2)+))
Run Code Online (Sandbox Code Playgroud)
重新运行提供的查询以检索特定文件的所有子节点,最终将看到“USERSTORE_SCHEMAMGR”内存管理员类型占用了大量已用资源。tempdb 也会不受控制地增长。
演示数据库查询太小,无法触发报告“内部”资源池的显式消息。但是,在同一台服务器上运行更大的查询应该会触发警告,并且性能仍然会受到影响。
以下查询可用于监控服务器性能:
-- Memory clerk usage
SELECT TOP(10) mc.[type] AS [Memory Clerk Type],
CAST((SUM(mc.pages_kb)/1024.0) AS DECIMAL (15,2)) AS [Memory Usage (MB)]
FROM sys.dm_os_memory_clerks AS mc WITH (NOLOCK)
GROUP BY mc.[type]
ORDER BY SUM(mc.pages_kb) DESC OPTION (RECOMPILE);
/*
Example output of above query:
Memory Clerk Type Memory Usage (MB)
------------------------------------------------------------ -----------------
USERSTORE_SCHEMAMGR 9224.26
MEMORYCLERK_SQLSTORENG 1114.73
MEMORYCLERK_SQLBUFFERPOOL 471.50
CACHESTORE_SEHOBTCOLUMNATTRIBUTE 376.47
MEMORYCLERK_SOSNODE 292.02
MEMORYCLERK_SQLGENERAL 19.84
MEMORYCLERK_SQLCLR 12.04
MEMORYCLERK_SQLQUERYPLAN 2.99
MEMORYCLERK_SQLLOGPOOL 2.61
MEMORYCLERK_SQLTRACE 2.14
*/
SELECT cache_memory_kb/1024.0 AS [cache_memory_MB],compile_memory_kb/1024 AS compile_memory_MB, used_memory_kb/1024.0 AS [used_memory_MB] FROM sys.dm_resource_governor_resource_pools
Run Code Online (Sandbox Code Playgroud)
为了快速查询服务器并消耗资源,我使用了以下 BASH 循环:
l=1000 # Number of loops
# The loop will probably need to be run 2M times or so to start to see significant usage.
c=0 # Loop tracker
touch marker # Alternate emergency stop: Remove the marker file from another terminal session.
time while [ $c -lt $l ] && [ -f "marker" ]; do
c="$((${c}+1))"
echo ${c}/${l}
# Notes: SQLCMDPASSWORD has been set in environment variable
# child-query.sql contains the above child query to loop for the children of file ID 1.
time sqlcmd -U db_user -S localhost -d DemoDatabase -i child-query.sql > /dev/null || break
done
rm marker
Run Code Online (Sandbox Code Playgroud)
DROPCLEANBUFFERS/FREEPROCCACHE/FLUSHPROCINDB DBCC 命令成功完成,但似乎没有效果。
是否有可以解决此问题的配置或程序,或者这是一个基本的服务器问题?
我是 Microsoft SQL 团队的一名项目经理,负责监督 SQL Graph 功能。感谢您提供的详细信息,并对问题表示诚挚的歉意。此问题已上报给我们的工程团队,并正在优先调查。我们会及时通知您调查结果。
2021 年 8 月 4 日更新:此问题已在SQL Server 2019 CU12 中修复。
PS 同时,作为参考,这里有一些提示,说明您还可以如何对引擎盖下发生的事情进行进一步的自我调查(如果您愿意)。首先,SQL Server 中的任何内存分配通常都可以使用扩展事件 (XE) 机制详细跟踪到调用堆栈级别。第一步是定义一个 XE 会话,过滤特定的内存管理员名称,在本例中为USERSTORE_SCHEMAMGR
:
CREATE EVENT SESSION [TraceMemObj] ON SERVER
ADD EVENT sqlos.page_allocated(
ACTION(package0.callstack)
WHERE (memory_clerk_name = 'USERSTORE_SCHEMAMGR')
)
,
ADD EVENT sqlos.page_freed(
ACTION(package0.callstack)
WHERE (memory_clerk_name = 'USERSTORE_SCHEMAMGR')
)
ADD TARGET package0.histogram
(SET source_type=1,
source=N'package0.callstack')
WITH (MAX_MEMORY=32768 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
Run Code Online (Sandbox Code Playgroud)
启动扩展事件会话:
ALTER EVENT SESSION [TraceMemObj] on server state = start
Run Code Online (Sandbox Code Playgroud)
然后,等待问题重现,然后运行以下查询。单击查询的 XML 输出。
SELECT event_session_address,
target_name,
execution_count,
CAST (target_data AS XML) AS MemObjData
FROM sys.dm_xe_session_targets AS xst
INNER JOIN
sys.dm_xe_sessions AS xs
ON (xst.event_session_address = xs.address)
WHERE xs.name = 'TraceMemObj';
Run Code Online (Sandbox Code Playgroud)
使用SQLCallStackResolver 可以将上述原始调用堆栈解析为更具可读性的版本。可读的调用堆栈将使您了解大部分分配的来源。
确保在问题重现一两分钟后停止 XE 会话:
ALTER EVENT SESSION [TraceMemObj] ON SERVER
STATE = STOP;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,对于您分享的再现场景,您会注意到顶部分配相关调用堆栈上的一些函数,这似乎表明与 SQL Graph 查询执行相关。
归档时间: |
|
查看次数: |
437 次 |
最近记录: |