故障表现
- 他的执行时间超过规定的限制(比如1000ms)
- CPU使用率高
- 大量业务失败,数据连接异常
- 执行sql越来越慢,失败越来越多
解决方案
定位 + 应急 + 故障恢复
定位
- 查询慢sql的日志
- 查看mysql 的performance schena(里面有锁和各种状态)和show processList
- 是否请求出现请求积压,是否数据库执行时间是否快速增加,出现超时
- 获取故障日志,查看异常的原因(是too many connection,还是超时)
- 查看连接池申请的连接数据量,并且定时查看。看是否连接数暴增,是否有连接数泄露的问题。还有是否有服务异常的使用了过多的连接数。
- 假如有缓存的话,是否出现缓存穿透、缓存雪崩等故障
- 如果存在主从多个节点的话,定位是否是单个节点出现故障/性能问题而导致异常,是否有某个节点登录不上
- 查看对应服务的日志量是否大量增加,请求的qps是否爆发性增长(由于用户压测、节假日高峰期、活动导致的qps瞬间增加)
- 是否有运维故意的写错sql、删库或者其他行为,导致数据库本身出现问题
- 是否有节点状态异常、重启、切换等(mysql添加心跳检测)。当节点挂的多的情况下,可能会导致其他节点受到太多的业务压力,从而导致节点异常连环崩溃
应急:
- show processlist,持续的杀掉慢查询的语句
- 对慢查询的sql进行溯源,定位调用方IP,然后直接封禁掉对应IP的地址
- 查询数据库节点对应的cpu占用 + 内存占用 + 磁盘占用
- 对数据库进行切流
- 扩容数据库副本数(这个没做过)
故障恢复
- 是否对高峰期的sql进行限流(需要改动代码)、熔断、降级
- 在可能的高峰期估算可能的qps,并申请设备、留足余量
- 优化sql + 索引,替换慢查询的语法
- 对数据进行反范式编程,允许一定的冗余以适应查询时间
- 对过期数据进行清理,或者将历史数据更换到其他数据库
- 备份binlog日志,然后对binlog进行解析,看sql占用时间
- 添加普罗米修斯等监控,保证数据库的成功率
- 对核心数据丢失进行人工补救