SQL Server设计运维避坑:12个实战关键点
|
去年一月份那破事儿我现在想起来还头疼——监控大屏突然闪红,开发组小王举着手机冲进机房,屏幕上堆了十八个SQL告警,全是“锁超时”。我原以为只是普通死锁,结果查日志发现是某个存储过程在循环里开了事务,外带没加NOLOCK提示,活生生把数据库卡成了PPT。后来一查,这存储过程还是三年前某位“大神”写的,注释里还写着“优化过,绝对高效”——高效个鬼,直接把线上业务干趴了四小时。 今天就着这破事儿,跟你们唠唠SQL Server设计运维里那些要命的坑。我总结了十二个关键点,别看多,每个都是拿血泪换来的。第一个最基础:别他妈乱用NOLOCK。我知道有人要说“不加NOLOCK查询慢”,但慢总比数据错强吧?去年有次财务系统报错,查了半天发现是某张报表加了NOLOCK,读到了脏数据,算出来的账差了七位数。开发还辩解“概率低”,概率低就不是错了?这要是审计查出来,够喝一壶的。 第二个坑是索引滥用。我见过最离谱的,有人给所有字段都建了索引,包括BIT类型的“是否有效”标志位。结果呢?插入一条数据要更新二十多个索引,磁盘IO直接拉满,CPU飙到90%。更搞笑的是,有些索引根本没人用——查执行计划发现,那些“精心设计”的复合索引,命中率连5%都不到。后来我让开发把没用的索引全删了,性能反而提了三十个百分点。所以说,索引不是越多越好,得看实际查询模式,别瞎建。 说到查询模式,第三个坑是忽略执行计划。有次线上查询突然变慢,开发说“代码没改”,我查执行计划发现,原本走索引的查询,突然变成了全表扫描。为什么?因为数据分布变了,统计信息没更新。SQL Server的统计信息是采样生成的,数据量大的时候容易不准,尤其是新增数据多的时候。所以定期更新统计信息很重要,AUTO_UPDATE_STATISTICS虽然能自动干这事,但有时候不够及时,建议手动跑一遍UPDATE STATISTICS,尤其是对大表。 第四个坑是事务设计不合理。就像开头说的那个存储过程,把事务开在循环里,还嵌套了其他存储过程,结果一个循环卡住,整个事务挂半天。事务要短,要快,要原子——能拆就拆,别贪心。我见过有人写事务,里面包含了网络调用、文件操作,甚至还调了外部API,这要是中间出点问题,回滚能回到你怀疑人生。事务里只做数据库操作,其他的一律别往里塞。 第五个坑是存储过程参数默认值。有次调用存储过程报错,查了半天发现是参数类型不匹配——调用方传的是INT,存储过程参数定义的是BIGINT,但默认值是NULL。SQL Server在隐式转换时出了问题,直接抛了异常。后来我规定,存储过程参数必须显式指定类型,默认值要么是明确的数值,要么是NULL,别搞那些模糊的玩意儿。模糊一时爽,排查火葬场。 窗外天黑了,外卖小哥刚送来一份黄焖鸡——得,边吃边唠。第六个坑是临时表滥用。有人喜欢用临时表存中间结果,觉得方便,但临时表会占用tempdb,数据量大的时候tempdb的IO能把你逼疯。我见过有人用临时表存几百万条数据,结果tempdb的日志文件涨到几十G,磁盘空间直接告急。后来我让他们改用表变量或者CTE(公用表表达式),性能反而更好,还不用操心tempdb的清理。 第七个坑是忽略错误处理。有次存储过程报错,开发说“我加了TRY-CATCH”,结果查日志发现,CATCH块里只写了“PRINT '出错了'”,连具体的错误信息都没记录。这有个屁用?后来我强制要求,CATCH块里必须记录错误信息,包括错误号、错误消息、调用堆栈,最好还把参数值也记下来。不然出了问题,你连从哪查起都不知道。
文章配图,仅供参考 第八个坑是链接服务器滥用。有人喜欢用链接服务器查其他库的数据,觉得方便,但链接服务器的性能差得离谱,尤其是跨服务器、跨实例的时候。我见过有人用链接服务器做报表,结果一个查询跑了半小时,还把网络带宽占满了。后来我让他们把数据同步到本地库,或者用SSIS包定期导入,性能提了不止一个量级。第九个坑是忽略参数嗅探。有次查询突然变慢,查执行计划发现,SQL Server用了个不合适的执行计划——因为第一次执行时传的参数值比较特殊,导致优化器生成了针对那个值的计划,但后续执行的参数值变了,计划就不适用了。这就是参数嗅探问题。解决的办法有几个:用OPTION (RECOMPILE)强制重新编译,或者用OPTIMIZE FOR提示指定常用参数值,或者用计划指南固定执行计划。别让SQL Server自己猜,它猜不准的。 第十个坑是忽略资源限制。有人觉得SQL Server是无限资源,想怎么用就怎么用,结果把CPU、内存、磁盘IO全占满了,其他业务跟着遭殃。我见过有人写查询,不加任何限制,直接扫全表,结果一个查询把CPU拉到100%,其他查询全挂起。后来我让他们加TOP、WHERE条件,或者用分页查询,把资源占用降下来。资源是有限的,得省着用。 第十一个坑是忽略备份策略。有人觉得备份是运维的事,开发不用管,结果出了问题才发现,备份没跑,或者备份文件损坏了。我见过有人把备份文件存到同一块磁盘上,结果磁盘坏了,备份也跟着没了。后来我让他们把备份文件存到不同磁盘,甚至不同服务器上,还定期做恢复测试,确保备份能用。备份不是形式,是保命的。 第十二个坑是忽略版本升级。有人觉得SQL Server不用升级,老版本用着挺好,结果遇到个BUG,发现官方早就在新版本里修复了,但自己没法用。我见过有人用SQL Server 2008,结果遇到个性能问题,查了半天发现是已知BUG,但官方只在2016及以后版本修复了。后来我让他们升级到新版本,问题直接解决。版本老不是稳定,是落后,该升还得升。 这十二个坑,说多不多,说少不少,但每个都是要命的。优胜劣汰,能避开这些坑的,才能活得久。我原以为这些坑都是基础,结果发现很多人还在踩——包括那些自称“资深”的。所以说,别觉得自己懂,多查、多测、多总结,才能少走弯路。今天就唠到这,黄焖鸡凉了,我得赶紧吃了。 (编辑:PHP编程网 - 金华站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


全栈建站者私藏的高效运维技术资源清单
直播+AI驱动电商增长:混合云运维新范式
站长必修:SQL Server缓存运维12大坑实录
DBA熬夜改表?这本MySQL实战手册让设计运维一步到位
Linux运维老手也常踩的5个Unix环境搭建陷阱
Windows多媒体站点权限配置:9年容器运维工程师的一键落地方案
前端站长亲历:12个高可用建站运维真相


浙公网安备 33038102330481号