记一次生产异常—数据库索引

记一次生产异常—数据库索引

小结

建立聚合索引时没有遵循最左匹配原则(本文不做该原理解析,大家可自行百度),导致索引命中后依然和全表扫描无异,加上数据量过大,导致数据库查询堆积,继而影响系统接口,系统不可用。

背景

在一次版本优化——重构表后,上线第二天,开始出现大量慢请求、请求超时,直至整个服务全部接口大量异常,导致系统不可用。该表的数据量日增在1000万+。

解决方式

在尝试了一次数据库连接池参数调整无效果后,选择了版本回退,但是因为回退时集群为串行逐台重启,从发现到回退完成耗时2个小时,在该期间系统处于异常情况,影响很大。

问题定位

1. 在版本回退后,开始根据当时的监控情况进行分析,首先明显是请求大量超时,单独分析超时请求发现都是数据库查询超时,观察数据库监控,发现cpu较平时增长一倍左右,连接数增长一倍左右。进一步分析慢请求,发现是sql执行时间过长导致,结合现象——一开始系统无异常,在用户高峰期时出现异常,怀疑是索引没有命中导致。
2. 一开始没有怀疑是慢sql导致是因为测试环境做了sql分析,索引建立也覆盖了查询条件。
3. 进一步分析索引,因为平时使用的是mysql,该系统使用的是tidb,虽然大部分和mysql相似,但是explain的sql执行计划却不一样,所以,开始更细致的了解tidb的执行计划和分析慢sql。很快就发现了问题所在——聚合(组合)索引建立错误导致。
4. 大部分查询是根据create_time,create_uer,customer_code, 所以建立索引时使用了index(create_time,create_user,customer_code),然而因为create_time 不是等值匹配,而是范围匹配,所以导致该聚合索引只能使用到create_time字段进行过滤,就出现了开头说的那个问题。

复盘

为什么在开发阶段没有发现这个问题?
首先,最最最最重要的是自己菜,没有理解聚合索引最左匹配原则,还停留在顺序这个错误的理解上。
其次,虽然每个查询的sql都使用了explain分析过,但是因为对执行计划的解读不足,看到了indexscan就认为命中了索引。
再者,一开始开发时,其实有写通过造数据模拟生产数据量级进行测试,但是在执行完explain的错误分析后,天真地以为问题,加上其他事情也很多,就偷懒省略了这一步。
最后,也是没有进行评审,这种关键改动是需要评审的,这也是没做好的一点。
为什么测试阶段没有发现这个问题?
第一,测试人力紧张,这次改动设计很多(表重构),测试点过多,加上还有其他项目占用测试时间,就没有做到很充分的测试。
第二,可能也是来自测试对开发的认可(手动加狗头, 哈哈哈哈哈)。
第三,确实也是开发和测试沟通不够导致测试用例没有覆盖这点。
为什么生产等到用户高峰期才发现这个问题?
该服务发版后,开发和测试都是没有生产账号进行测试回归的,只能看了当时的日志没有异常后,认为没有问题,所以才有这种第二天高峰期数据量增长上来之后暴雷的情况。

谁的问题?

这个毋庸置疑,百分之百是开发人员,对没错,就是我,需要承担百分之一百的责任。

今后如何避免此类问题

  1. 多学多看
  2. 不能偷懒,敢做的步骤不能因为别的步骤有保障就省略,因为别的步骤可能会出错
  3. 关键改动、接口等一定要进行人工的交叉评审,这一步其实可以避免很多问题,但是耗费较多人力。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值