前言
近期,项目的云盘服务在例行压测中发现了新的问题,出现数据库 cpu 负载过高造成 VIP 漂移,导致短时间不可用的情况。
但是压测环境近一个月都没有进行更新,前面几次还是正常的,怎么突然就出现问题了?
故障复盘
同事查阅日志后发现,数据库是因为打开文件数过多,导致 cpu 使用率飙升,最后宕机了。
翻查慢SQL,发现如下图这一 SQL 语句,explain 分析状况,子查询 + 连表查询多达18次,其中主要数据表已达百万级别,且在 SQL 语句内使用了3次以上。
归根到底,是因为大表连表使用过多,在并发调用情况下,数据库服务器打开了太多的文件去进行查询,最后导致 cpu 负载飙升而崩溃。
从业务上来看,这是一个用于文件递归搜索的 SQL 语句。
但是,文件夹与文件之间有父子关系。
另外,这里还有权限筛选,权限也有继承关系,如:继承最近父文件夹的权限、继承最邻近一个父级部门的权限、子文件可见则父文件夹可见等等;
最后,导致组装出来的这一个 SQL 语句过于累赘了。在数据库数据量日渐增长的情况下,直到到达某个阈值,故障炸弹引爆。
解决方法
那么,为了从根源上解决问题,我们需要去优化 SQL 语句。
因为这个接口本来被用于一个分页列表,所以所有筛选条件都通过了数据库来做,并进行分页。
在数据量可控的情况下,分页其实可以由代码来做。即数据库只查询出所有满足部分条件的数据,其他条件再从代码层面去筛选(如权限控制)。
当然,从 UI 交互上来说,在文件搜索这一场景,瀑布式列表可能会比分页式更好,而瀑布式每次加载完全没必要等同数量,那么接口处理逻辑就最终可以变成这样:
通过拆分 SQL 语句,及代码逻辑弥补的处理,大大减少数据库查询的文件打开数,来适应数据量日益增长的情况。
以上就是小编对一次由 SQL 引发的数据库文件数打开过多,宕机引发的故障复盘,及解决历程的记录。
希望对大家有所帮助,感谢阅读~
以上就是本期分享,如果大家对此感兴趣,欢迎各位关注、留言,大家的支持就是我的动力!