加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0354zz.com/)- 科技、容器安全、数据加密、云日志、云数据迁移!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

站长SQL Server运维避坑指南:12大故障实战复盘

发布时间:2026-10-12 10:55:19 所属栏目:MsSql教程 来源:DaWei
导读:文章配图,仅供参考  去年六月份那波故障,我现在想起来还后怕——监控突然狂报警,慢查询堆得跟山似的,开发在群里喊“页面卡爆了”,运维冲进来看了一眼屏幕,风扇转得嗡嗡响,说了句“这得跑俩小时吧?”扭头就走了。我原以为只

文章配图,仅供参考

  去年六月份那波故障,我现在想起来还后怕——监控突然狂报警,慢查询堆得跟山似的,开发在群里喊“页面卡爆了”,运维冲进来看了一眼屏幕,风扇转得嗡嗡响,说了句“这得跑俩小时吧?”扭头就走了。我原以为只是常规的索引失效,结果查日志发现是某个存储过程里嵌了三层子查询,参数还用了动态SQL拼接,执行计划直接炸了。最绝的是,这破代码是三年前一个离职的“大神”写的,注释里还写着“性能优化版”——优化个锤子!

  那天从中午十二点搞到晚上八点多,外卖凉了都没顾上吃。先是用SQL Server Profiler抓了半小时,发现某个大表的全表扫描占用了90%的CPU,表里数据倒是不多,就两百万条,但有个NVARCHAR(MAX)的字段,里面存的是JSON格式的配置,每次查询都要解析。开发说“这字段我们只读不写”,我差点笑出声——只读不写就不用建索引?后来硬是逼着他们改成了NVARCHAR(4000),再加个计算列存JSON长度,配合一个非聚集索引,慢查询才消停。不过这事儿最坑的是,他们改完没测全量,第二天又爆了个“算术溢出错误”——原来有些JSON里存了超长的数字,计算列直接截断了。

  说到备份,那天还差点栽跟头。主库的备份策略是每天全量+每小时差异,结果查备份链的时候发现,差异备份从上周五开始就没成功过——存储空间满了,但监控没报!运维说“我设置了阈值警报啊”,结果一查,警报脚本里写的是“当剩余空间小于10GB时触发”,而我们的备份盘总共就20GB,周五那天差异备份刚写了8GB,剩下的2GB根本不够全量备份跑。最后只能临时挂了个移动硬盘,手动备份,差点耽误了第二天的数据同步。这事儿之后我改了规则:剩余空间小于50%就报警,而且必须发邮件+短信,光靠脚本不行——上次运维休假,脚本挂了三天都没人知道。

  还有一次更离谱,是主从延迟的问题。业务方反馈“订单状态更新不及时”,查了半天发现是主库的WAL日志积压了。我原以为是网络带宽不够,结果用sp_who2一看,有个会话的wait_type是“PAGEIOLATCH_SH”,阻塞了其他事务。进一步查发现,是某个大表的非聚集索引碎片率到了90%,但重建索引的作业被卡住了——因为表上有外键约束,而从库的对应表没建索引,导致重建时需要校验数据一致性,结果从库响应慢,主库就跟着堵。最后只能先在从库上补索引,再重建主库的索引,前后折腾了四个小时。业务方在群里催了二十多次,领导还私聊问我“能不能优先处理”,我回了句“正在修,但得按流程来”——不然修完更乱。

  对了,那天还跟开发吵了一架。他们非说“慢查询是SQL Server的锅,MySQL就不会这样”,我直接甩了张截图——他们写的SQL里有个LEFT JOIN,关联条件是“WHERE b.id IS NULL”,但表b的id字段没建索引,导致每次都要全表扫描。我说“这换哪个数据库都得慢”,他们还不服,说“我们本地测试没问题”。我让他们把测试环境的表数据量导到和线上一样,再跑一遍——结果跑了十分钟没出来,他们才闭嘴。后来我查了下,测试环境的表就一万条数据,线上的表有一千万条,这能一样吗?

  说到测试环境,我想起个更扯的事儿。有次业务方说“某个报表加载慢”,开发在测试环境复现不了,说“线上和测试环境配置一样啊”。我让他们把线上和测试环境的SQL Server版本、内存分配、并发连接数、甚至操作系统版本都列出来,结果发现测试环境用的是SQL Server 2019开发者版,线上是2019企业版——虽然核心功能一样,但企业版的查询优化器更激进,有些执行计划会不一样。更绝的是,测试环境的表数据是导的线上的备份,但导的时候没导统计信息,导致优化器选了错误的执行计划。后来我让他们在测试环境手动更新统计信息,再跑——慢了三倍。开发这才承认“确实没测全”。

  现在回头看,这十二大故障里,能活下来的都是“优胜劣汰”的结果——那些没监控的、没备份的、没索引的、没测试的,早就被业务方骂死了。但有些坑,真的是防不胜防。比如上周五,运维手抖把主库的恢复模式从“完整”改成了“简单”,结果周六的日志备份没生成,周一发现的时候,周日的数据已经没法做时间点恢复了。还好业务方没删数据,只能从全量备份里恢复,再手动补交易记录——补了两天,业务方差点掀桌子。我问运维“你怎么改的配置?”,他说“我就点了个下拉框,没注意看当前模式”——我信了他的邪,后来查操作日志,发现他是在生产环境直接改的,测试环境都没试。

  现在我们的规矩是:改配置必须先在测试环境验证,再写变更文档,最后由两个人确认——其中一个人必须是我或运维主管。但就算这样,还是会有漏网之鱼。比如上个月,开发新上了一个功能,用了个新的存储过程,里面有个事务没加TRY-CATCH,结果运行时抛了个死锁错误,事务没回滚,数据直接乱了。业务方反馈“订单金额不对”,查了半天才发现是存储过程的问题。我问开发“你们没测异常情况吗?”,他说“测了,但没测死锁”——我差点气笑,死锁是SQL Server的常见问题,怎么能不测?后来我让他们把所有存储过程都加上TRY-CATCH,再配个错误日志表,把异常信息存下来——不然下次出问题,还是抓瞎。

  现在想想,这些故障里,有一半是“人祸”——要么是手抖,要么是没测全,要么是瞎改配置。剩下的才是技术问题,比如索引失效、执行计划错误、主从延迟。但技术问题好解决,人祸难防。我现在的要求是:任何变更必须留记录,任何异常必须报警,任何操作必须双人确认——就算慢点,也比出故障强。不过话说回来,就算这么严,还是会有漏的——比如上周三,运维在维护窗口期重启了主库,结果有个长事务没提交,重启后事务丢失了,数据不一致。业务方反馈“用户余额不对”,查了半天才发现是这个问题。我问运维“你怎么不先杀长事务?”,他说“我以为维护窗口期没用户操作”——我信了他的邪,用户24小时都在操作,哪来的“没用户”?

  现在我们的监控已经覆盖了90%的场景,但那10%的“未知未知”才是最可怕的。比如上个月,磁盘突然坏了,备份盘也坏了——双盘故障,数据全丢。还好我们有离线备份,放在另一个机房,但恢复的时候发现,离线备份是三个月前的,最近三个月的数据没了。业务方差点疯,最后只能手动补——补了半个月,才补完。我问运维“你们没做多副本备份吗?”,他说“做了,但另一个副本在同一个机房”——我直接骂人,同一个机房的备份,遇到火灾或停电,还不是全丢?现在我们的规矩是:备份必须跨机房、跨城市,甚至跨云——就算贵点,也比丢数据强。不过话说回来,就算这么备,还是有可能丢——比如云服务商出故障,或者地震洪水。但至少,我们能做的都做了,剩下的,只能看运气了。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!