昨天下午博客园又崩了,不过与其它大厂的崩溃不同,博客园出现崩溃的频率好像有点高。
这是怎么回事呢?和阿里云又有什么关系,这篇文章就来分析分析。
到底是谁的问题?
昨天下午(2023年12月8日)博客园官方发布了一个故障公告,官网截图如下:
博客园的故障是数据库CPU 100%,今年已经出现了7次,根据我这个不经常上博客园的人的观察,往年也有出现,好像频率没这么高。
出现了7次都不能解决,这是个什么问题呢?
根据我的技术经验,数据库CPU百分之百,一般是某些SQL写的质量不佳,在某些情况下可能出现了大数据量全表扫描的情况,迟迟不能执行完毕,长期霸占CPU资源导致的。
按说这种问题只要定位到对应的SQL,改掉相关语句就可以了,但是就是这个问题把博客园难住了。
参数嗅探问题?
看看官方针对此次问题的说明:
这里有两个重要的信息:博客园的数据库使用的是 SQL Server;博客园的主要查询使用的是存储过程。博客园是.NET技术体系的,使用SQL Server比较顺其自然;使用存储过程可以提高SQL执行的效率,博客园是08年创立的,这在十几年前也比较流行;看它使用的分页方法也是比较新的,这说明它也一直在优化。
官方怀疑是参数嗅探问题造成 SQL Server 缓存了性能极差的执行计划,这句话中有两个名词:参数嗅探问题和执行计划,没接触过的同学可能会比较蒙,我先给大家普及一下。
执行计划:每条SQL在数据库内部执行时都会有一个执行计划,主要就是先查询哪张表、表之间怎么关联、执行的时候使用哪些索引,等等。
参数嗅探问题:存储过程在首次执行时会先进行编译,后续执行的时候都使用这个编译的结果,而不是每次都解释执行,因为编译相对比较耗时。编译时,数据库还会根据当前使用的存储过程参数确定一个最优的执行计划,并把这个执行计划也一并缓存起来,后续再执行的时候就会直接使用这个执行计划。
问题主要就出现在这个缓存的执行计划,因为对于不同的参数来说,执行计划的效率可能差别很大,这主要是查询数据分布不均匀的问题造成的。
我在公司的业务中也经常遇到这个问题,有的用户数据多,有的用户数据少,即使我们为用户Id字段设置了索引,数据库有时仍旧会认为不使用这个索引的效率更高,它会自己选择一个自认为更优的查询路径,比如全表扫描,实际执行时就出现了慢SQL的情况。
到博客园这里,官方认为就是自己的某个存储过程因为参数嗅探问题导致某些慢SQL,慢SQL导致CPU使用过高,最后导致数据库崩溃。
而官方一直没有定位到出现问题的SQL或者出现问题的存储过程,可能博客园的SQL太多了吧,出现问题的不止一个SQL。又或者是 SQL Server 的问题,或者阿里云的锅?
SQL Server的问题?
SQL Server 作为一款商业数据库,能活到现在,而且价格还不低,其产品能力是经过了残酷的市场考验的。虽然任何产品都不可避免的存在一些BUG,但是导致这种问题的BUG应该不会持续这么久。所以 SQL Server 本身的问题应该不大,或者说 SQL Server 的数据查询方式没有问题。
还有很多同学提到 SQL Server 性能不行,单纯根据我的使用经验来说,类似的场景 SQL Server的查询性能往往比 MySQL 要好不少,其它很多用户也有类似的反馈:
我也专门找了一些 SQL Server 和其它数据库的性能对比,截图如下:
文章和数据来源:
https://segmentfault.com/q/1010000022848400
https://www.ijarcce.com/upload/2015/march-15/IJARCCE%2039.pdf
另外我们也可以从博客园分享的数据库的监控日志中略窥一二:
从图上可以看出,出现问题的时间比较随机,也不是什么高峰期。博客园也提到过凌晨4-5点钟出现类似问题。看这个CPU使用率只有20%多一点,所以并非是遇到了性能瓶颈。
阿里云的问题?
阿里云为什么可能背锅?因为博客园部署在阿里云上,服务器和数据库都用的阿里云产品。
记得之前出现这个问题时,博客园官方对阿里云颇多微词,后来双方可能进行了深入交流,博客园接受了参数嗅探问题,此后就一直在这块查找。
那么阿里云能不能彻底撇清关系呢?
正常情况下,阿里云上部署的 SQL Server 应该是从微软购买的,微软应该也要提供一些技术支持,包括安装和日常的运行维护支持。这个 SQL Server 可能和 Azure 上部署的有些差别,但微软也不会砸自己的招牌,数据库版本不应该有大问题。
阿里云只是部署和运维 SQL Server,说白了阿里云只是搞了底层的存储、网络、操作系统等服务,上层的数据库应用完全是微软的,他插不上手,这种数据库程序的CPU百分百的故障很难和阿里云干的事挂上钩。
再者阿里云自己也开发数据库,虽然 SQL Server 不开源,但是高手们对于一些底层的设计,或者可能存在问题的地方,应该也是门清的。阿里云上 SQL Server 服务使用者众多,如果很多企业都遇到这个问题,应该也早就爆出来并解决了。
所以这个问题甩锅到阿里云身上的难度比较大。当然也没办法完全排除,毕竟总有些极端情况,阿里云最近也崩了很多次,会不会在某些方面有些幺蛾子?大家也不知道。
怎么解决问题?
换数据库?
正如上文所说,问题出现在数据库自身上的可能性不大,而且换数据库要重写所有的SQL,还可能要修改表结构,这个工作量不是一星半点。
如果真的是参数嗅探问题,换了数据库一样存在执行计划效率不一致的问题。
换云?
这基本是认为阿里云能力不行。
如果真的怀疑是这方面的问题,倒是可以试试,不过不是直接迁移过去,而是把数据导出来一份,放到别的公有云上,或者本地部署一套SQL Server。
然后采集SQL执行日志,在测试的数据库中进行重放执行,如果问题还会发生,那就不是云厂商的问题,如果跑了很久,问题都没有出现过,那才有根据说云服务的问题概率比较大一些。
当然这个测试的成本比较高,也许可以通过精简样本或者提高SQL执行频率加速一下测试。
作为技术人,甩锅时一定要有理有据。
再或者就不讲理,博客园死磕阿里云,要么就是你的问题,要么就是你帮我找出问题来。有时候云厂商的技术团队也是可以上门或者以其他方式进行亲密沟通的。再不行花点钱找个高手呢?可能还是博客园太老实了?或者阿里云太傲慢了?又或者博客园太穷了?
解决慢SQL/参数嗅探问题
阿里云的问题只能是猜测,参数嗅探的问题确是能够实实在在抓住的,阿里云的数据库产品是提供了慢SQL日志查询的。
只需要找出出现问题时的慢SQL,看博客园以往的故障公告也是曾经抓到过一些问题SQL的。
但是问题为什么还会一直出现呢?
有可能是问题SQL太多了。经过十几年的迭代,博客园的代码量可能十分庞大,再加上博客园这两年经营比较困难,没有人力和精力投入到这方面,只能问题出现了再去反查,然后改正。能活着就不错了,估计团队内部也没有技术牛人,精力都放到了活下来的事情上。
具体为什么一直解决不了,咱们就说到这里。
下面给大家聊聊怎么解决参数嗅探的问题,我想这个对于搞技术的同学来说才是最重要的.
上面我们已经说过参数嗅探问题就是数据库使用了效率不高的执行计划,那么解决这个问题的核心思路就是让数据库不去使用这些低效计划。这里分享一些我了解的方法。
暴力清理
重启服务器、重启数据库,博客园采用的处理方法差不多都是这个。
还有一个稍微优雅点的方案,清除所有的执行计划缓存:DBCC FREEPROCCACHE,不管这些执行计划是不是有问题。但是不确定这个指令能不能在阿里云的数据库服务上执行。
这些都是强制重新创建执行计划的方法,坏处就是影响都比较大,很可能会影响用户使用服务,比较暴力。
而且这些方法不能治本,只能短时间的缓解一下,说不定在某个时刻,执行计划又被重建了,或者SQL执行又超时了。
优雅机制
SQL Server本身也有一些优雅的方案来缓解这个问题。比如:
不缓存执行计划,虽然缓存能带来一些效率上的提升,但相比参数嗅探问题带来的性能损失就是小巫见大巫了。可以在存储过程中使用WITH RECOMPILE,让查询每次都重新编译。
强制使用某个查询计划,比如强制使用某个索引,这个索引对于所有的查询都不会太差;SQL Server中还可以强制使用某个条件的查询计划。不过找到这个索引或者条件的难度可能比较大,因为数据一直在变化,现在是好的并不代表一直好。
只清除特定语句或存储过程的查询缓存,使用 DBCC FREEPROCCACHE(@plan_id) 指定执行计划,这样影响更小。
另外表统计信息陈旧、索引碎片、缺少索引都可能导致参数嗅探问题,遇到问题时可以从这几个方面调查一下。
详情可参考阿里的这篇文章: http://mysql.taobao.org/monthly/2016/10/10/
谨慎评估
在我们设计表、编写SQL的时候,需要考虑数据会如何分布,查询有哪些条件,特别是数据可能分布不均匀的情况。
比如有的用户的数据量可能是大部分用户的10倍、甚至百倍,排序的字段可能导致不使用包含条件字段的索引,查询可能在多个索引之间飘移。
如果可能存在问题,就要考虑表如何设计、数据如何查询,普通关系数据库难以解决时,我们还可以考虑采用NoSQL、分布式数据库等方案,以稳定查询效率。
以上就是本文的主要内容了,因本人才疏学浅,不免存在错漏,如有问题还望指正。
关注萤火架构,技术提升不迷路。