sqlserver 出现dump文件分析
背景
例行检查某项目的数据库日志信息,发现出现比较频繁的dump,这个风险需我们紧急介入,需分析该问题的原因、有多严重、并修复;
服务器环境情况如下:
Microsoft SQL Server 2016 (SP1) (KB3182545) - 13.0.4001.0 (X64) Oct 28 2016 18:17:30 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows Server 2012 R2 Datacenter 6.3 <X64> (Build 9600: ) (Hypervisor)
操作步骤
首先先核实出现DUMP的时间、次数等信息;
select *from sys.dm_server_memory_dumps
发现出现了160次,最近一次是2019年10月8日,挑选最新一次的dump信息分析如下:
查看SQLDump0160.txt发现如下信息,基本可以确定出现dump的原因是由于索引损坏,也知道是什么脚本触发该问题;
使用windbg分析SQLDump1060.mdump如下:
STACK_TEXT: 0000003f`8511a180 00007ff7`ba549c9c : 00000000`00011000 00007ffe`21973c10 0000003f`8511a2c4 0000003f`00000004 : KERNELBASE!RaiseException+0x68 0000003f`8511a260 00007ffe`22e802c6 : 00007ff7`ba58bd80 00007ffe`2d101118 00000000`00000000 0000003f`8511a458 : sqlservr!CDmpDump::Dump+0x4c 0000003f`8511a2a0 00007ffe`2397c411 : 00007ff7`ba58bd80 00000000`00000460 00000000`00000000 00007ffe`2d101616 : sqllang!SQLDumperLibraryInvoke+0x1f6 0000003f`8511a2e0 00007ffe`2397ce94 : 00000000`00021164 00000000`58f1f705 00000000`00000000 00007ffe`24cdfe30 : sqllang!SQLLangDumperLibraryInvoke+0x161 0000003f`8511a390 00007ffe`2394cd0b : 0000004b`00f94a70 00000000`58f1f705 0000004b`00f94a70 0000004b`00f95910 : sqllang!CImageHelper::DoMiniDump+0x475 0000003f`8511a5a0 00007ffe`2586da80 : 0000005b`23a228a0 0000005b`23a228a0 0000003f`8511c330 00000000`000000bf : sqllang!stackTrace+0x9db 0000003f`8511bfc0 00007ffe`2586dc42 : 00007ffe`272f30a0 00000043`f2488fc0 00000000`00000000 00007ffe`24f7ac2d : sqlmin!IndexFailure_ErrorAbort+0x1d1 0000003f`8511c2d0 00007ffe`25109860 : 00000046`00000005 00000043`f2488fc0 00000000`00000003 0000003f`58f1f705 : sqlmin!CPerIndexMetaQS::ErrorAbort+0xc3 0000003f`8511c330 00007ffe`22091de7 : 00000043`f2488fc0 00000046`00000001 0000003f`8511c420 00000043`08f72bc8 : sqlmin!CValRowMult::SetDataX+0x386 0000003f`8511c400 00007ffe`24f41c29 : 00000000`00000001 00000043`08f72bc0 00000000`00000000 00000043`08f72150 : sqltses!CEsExec::GeneralEval4+0xe7 0000003f`8511c4d0 00007ffe`24f05caf : 0000003f`8511c7a9 00000043`08f72bc0 00000000`00000000 00000041`65c78870 : sqlmin!CQScanUpdateNew::GetRow+0x314 0000003f`8511c580 00007ffe`229365d7 : 00000000`00000000 00000000`00000000 7fffffff`ffffffff 00007ffe`229378a2 : sqlmin!CQueryScan::GetRow+0x81 0000003f`8511c5b0 00007ffe`22c79a79 : 00000043`08f72150 0000004b`00f94a70 00000000`00000000 00000000`00000000 : sqllang!CXStmtQuery::ErsqExecuteQuery+0x4dc 0000003f`8511c730 00007ffe`22c7983c : 0000003f`eb082101 0000004e`34f25a00 00000000`00000000 0000004b`00f94a01 : sqllang!CXStmtDML::XretDMLExecute+0x3a3 0000003f`8511c810 00007ffe`235a0de2 : 0000004b`00f94a70 0000004b`46002560 0000003f`8511c950 00000041`83cbe8f0 : sqllang!CXStmtDML::XretExecute+0xb0 0000003f`8511c840 00007ffe`22d172af : 0000004b`46002000 00000000`00000000 00000000`00000000 0000004b`00f94a00 : sqllang!CMsqlExecContext::ExecuteStmts<1,0>+0x1603 0000003f`8511cf20 00007ffe`22932041 : 00000041`83cbe7c8 00000000`00000000 00000041`83cbe700 00000000`00000000 : sqllang!CMsqlExecContext::FExecute+0xaa5 0000003f`8511d250 00007ffe`2363d83d : 00000000`00000000 00000000`00000007 00000041`83cbec20 00000000`00000000 : sqllang!CSQLSource::Execute+0x983 0000003f`8511d3f0 00007ffe`2363d241 : 00000041`83cbec20 00000041`83cbe7c8 00000041`0439ab80 00000000`00000000 : sqllang!CStmtExecProc::XretLocalExec+0x26e 0000003f`8511d470 00007ffe`23639f98 : 00000000`00000000 00007ffe`22a99773 00000041`83cbe710 00000000`00000000 : sqllang!CStmtExecProc::XretExecExecute+0x481 0000003f`8511dc20 00007ffe`235a0de2 : 00000041`83cbe560 0000004b`00f94a70 00000000`00000002 0000004b`00f94b08 : sqllang!CXStmtExecProc::XretExecute+0x38 0000003f`8511dc60 00007ffe`22d172af : 00000000`00002000 0000004b`00fac990 00000000`00000000 00007ffe`00000011 : sqllang!CMsqlExecContext::ExecuteStmts<1,0>+0x1603 0000003f`8511e340 00007ffe`22932041 : 0000004b`00fac890 00000000`00000000 0000004b`00fac800 00000000`00000000 : sqllang!CMsqlExecContext::FExecute+0xaa5 0000003f`8511e670 00007ffe`2293a82b : 00000000`00000000 00007ffe`00000007 00000000`00000000 0000004b`00000000 : sqllang!CSQLSource::Execute+0x983 0000003f`8511e810 00007ffe`22941542 : 0000004b`00fea700 0000004b`00fea430 00000000`00000000 0000004b`00fea400 : sqllang!process_request+0xe61 0000003f`8511ede0 00007ffe`229410a3 : 00000000`00000000 0000003f`eb082148 0000003f`eb082148 00000000`00000000 : sqllang!process_commands_internal+0x2df 0000003f`8511ee60 00007ffe`21bc5bfd : 0000004b`00febb20 00007ffe`21bc3add 0000003f`ffffffff 00000000`000027ae : sqllang!process_messages+0x253 0000003f`8511f070 00007ffe`21bc58f5 : 0000003f`eb082148 0000003f`eb082108 0000003f`eb082190 ffffffff`00000000 : sqldk!SOS_Task::Param::Execute+0x231 0000003f`8511f670 00007ffe`21bc554d : 0000004e`91220040 0000003f`8511f759 0000004e`91220040 0000003f`eb088160 : sqldk!SOS_Scheduler::RunTask+0xaa 0000003f`8511f6e0 00007ffe`21bed7c8 : 00000000`00000000 0000003f`eb088160 0000003f`eb088160 00007ffe`21bedf00 : sqldk!SOS_Scheduler::ProcessTasks+0x3cd 0000003f`8511f7c0 00007ffe`21bedb10 : 0000003f`eb088160 00000000`00000000 0000003f`eb088160 000105a0`65812f97 : sqldk!SchedulerManager::WorkerEntryPoint+0x2a1 0000003f`8511f890 00007ffe`21bedcd7 : 0000003f`eb088160 0000003f`8511f930 0000004e`91080280 0000003f`e7cd0590 : sqldk!SystemThread::RunWorker+0x8f 0000003f`8511f8c0 00007ffe`21bed9f8 : 0000004e`91080230 00000000`00000000 00000000`00000000 0000004e`91080170 : sqldk!SystemThreadDispatcher::ProcessWorker+0x2de 0000003f`8511f970 00007ffe`2f9f13d2 : 00000000`00000000 00000000`00000000 0000003f`e7cd0590 0000003f`e7cd0590 : sqldk!SchedulerManager::ThreadEntryPoint+0x1d8 0000003f`8511fa20 00007ffe`2fd454f4 : 00007ffe`2f9f13b0 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0x22 0000003f`8511fa50 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x34
保险起见先搜索官方是否有FIX之类的参考文档。
查看上述文档对应的最新sql server版本是2014,而我们使用的2016默认上述文档中问题应该是已修复的;后续在2016的SP2的列表中也未找到修复本案例相关的问题的描述;
既然已确定是索引损坏,那接下来的问题就是确定是哪个表、什么索引损坏了。
通过上面的SQLDump0160.txt我们知道是执行存储过程【sfa_p_updatestorestatus】引起的dump,查看该存储过程代码如下:
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[sfa_p_updatestorestatus]
-- Add the parameters for the stored procedure here
@guid varchar(50) ,
@status int,
@xwUserNumber int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
UPDATE sfa_t_store set status=@status,updateop=@xwUserNumber,updatetime=getdate() where guid=@guid
END
发现该存储过程就是简单更新【sfa_t_store】这个表的操作,那么接下的问题就更简单了直接检查该表即可。本来还想可能需checkDB才行;
dbcc checktable('dbo.sfa_t_store')
消息 8951,级别 16,状态 1,第 7 行
表错误: 表 'sfa_t_store' (ID 1492252421)。数据行在索引 'IX_sfa_t_store_saleareaidGuid' (ID 3)中没有匹配的索引行。与以下数据行匹配的索引行的键可能丢失或无效:
消息 8955,级别 16,状态 1,第 7 行
数据行(1:1132194:0)由(storeid = 419448)标识,索引值为“saleareaid = 'D7B30A46-25F9-41C6-AECB-5838915B0EF8' and guid = 'B777C7B2-1079-4483-8CE1-427379BD9D9C' and status = 1 and storeid = 419448”。
消息 8951,级别 16,状态 1,第 7 行
表错误: 表 'sfa_t_store' (ID 1492252421)。数据行在索引 'IX_sfa_t_store_saleareaidGuid' (ID 3)中没有匹配的索引行。与以下数据行匹配的索引行的键可能丢失或无效:
消息 8955,级别 16,状态 1,第 7 行
数据行(1:1132193:11)由(storeid = 419446)标识,索引值为“saleareaid = 'D7B30A46-25F9-41C6-AECB-5838915B0EF8' and guid = '7FCC1380-EE39-46D4-A4F7-A48466E674D1' and status = 1 and storeid = 419446”。
消息 8951,级别 16,状态 1,第 7 行
表错误: 表 'sfa_t_store' (ID 1492252421)。数据行在索引 'IX_sfa_t_store_saleareaidGuid' (ID 3)中没有匹配的索引行。与以下数据行匹配的索引行的键可能丢失或无效:
消息 8955,级别 16,状态 1,第 7 行
数据行(1:1132193:12)由(storeid = 419447)标识,索引值为“saleareaid = 'F1CCE355-387A-4CB3-A878-F33166E913E4' and guid = '45805C83-EC07-40CB-A810-4D6E2EBFF299' and status = 1 and storeid = 419447”。
sfa_t_store的 DBCC 结果。
对象 'sfa_t_store' 的 105452 页中有 1351236 行。
CHECKTABLE 在表 'sfa_t_store' (对象 ID 1492252421)中发现 0 个分配错误和 3 个一致性错误。
对于由 DBCC CHECKTABLE (*******.dbo.sfa_t_store)发现的错误,repair_rebuild 是最低的修复级别。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
从检查结果来看都是【IX_sfa_t_store_saleareaidGuid】损坏,好消息的是该索引不是聚焦索引,那么接下来的动作就是直接删除该索引重新新建即可,类似聚焦索引的修复可以参考质疑页修复实践
drop index IX_sfa_t_store_saleareaidGuid on dbo.sfa_t_store
CREATE NONCLUSTERED INDEX [IX_sfa_t_store_saleareaidGuid] ON [dbo].[sfa_t_store]
(
[saleareaid] ASC,
[guid] ASC,
[status] ASC
)
INCLUDE ( [storecode],
[storename],
[storetype],
[contactname],
[contactphone],
[authorityKeywords]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
重新检查该表已正常;