- 继上次Redis 事件之后, 最近运维收到广告系统的
MySQL
告警信息 - 然后让我排查一下最近代码是不是有什么改动, 从而导致数据库负载升高. 如图:
- 很明显的可以看出来, 在图中的鼠标所在的时间点, 负载瞬间升高, 然后一直持续没有降下去.
- 我赶紧打开
Git
查看一下当天提交的代码, 发现当天并没有代码提交部署, 所以可能是运营配置导致的. - 打开阿里云的
SQL洞察和审计
功能(其它云厂商也有类似的数据库审查服务)
- 如图, 很快就可以定位到这条有问题的
SQL
, 对比于其它查询占比了90%+
- 接下来的事情就很简单了, 直接找到这条
SQL
对应的代码, 然后分析一下:- 之前同事写这段代码时, 运营只配置了一个, 现在运营允许配置有多个选项
- 没有使用缓存
- 随后优化了一下这段代码的查询逻辑, 并加上相应的缓存处理
- 修改完之后, 可以看到数据库负载降下去了, 但是另外一条
SQL
的占比变高了, 并且由于是使用了where exists
可以看到平均耗时远远大于其它SQL
- 一样的方式定位到
SQL
对应的代码- 在
Laravel
中使用了whereHas
生成这个where exists
, 由于外表的数据集比较多, 导致查询比较慢 - github 有好几个解决方法, 无非就是
where in
替代掉where exists
- 然后按着这个方案自己写了一些代码修复好, 也可以使用第三方包来处理
- 在
- 如上图, 处理好后的查询语句基本都比较均匀了
- 并且数据库负载也降低到
1%
了, 同时期的负载在50%
左右