mysql表更改字段类型未更改sql导致索引失效

【影响范围】
所有用户不可登录,21:00左右恢复登录,但某业务服务A不可用,且恢复的业务功能也不能稳定服务

【故障表现】
18:30开始,收到大量服务报警,随后服务压力井喷式上升,CPU使用率接近800%,最后全网服务不可用

【处理过程】
2020-08-28 18:30 左右发现大量服务报警,业务服务处于不可用状态。业务服务数据库压力陡增,CPU 使用率近 800%。

通过 show processlist 和 show engine innodb status 查看数据库线程信息和 InnoDB 引擎状态,发现大量的查询被阻塞。但是并没有明显的证据表明是哪个 SQL 引起的。

由于执行过大表的 RENAME 操作,初步怀疑问题跟 RENAME 有关,为了快速恢复业务服务,期间重启了数据库服务,然而并没有什么效果。

随后执行了数据库的主从切换,将从库作为主库提供服务,发现从库压力陡增,所以初步排除是数据库服务器本身的问题。

实际上 RENAME 操作是速度很快的,秒级完成,不会引起锁表,可以放心执行。
至此,尝试过了重启数据库,切换从库,问题均没有任何缓解,排除数据库自身问题,那么问题很有可能就是由于慢查询引起的。

但是此时数据库中存在大量慢查询等待,涉及到的服务众多,最终只能通过排除法逐个排除,有一些公共服务被阻塞的请求比较多,初步怀疑是这两个服务引起的,关闭服务后发现问题依旧没有解决。

后来了解到当晚是对 某个数据库A的表结构做了变更,而且上线的了几个服务都与这个数据库有关,因此开始怀疑是这个数据库A账号引起的。但是由于是服务重构过度期间,使用这个账号的服务有很多,
为了节省处理问题的时间,将数据库A账号的所有权限回收,以便快速验证

REVOKE ALL PRIVILEGES ON database_name.* FROM ‘database_name’@‘%’;
强制 flush 权限,以断开所有的数据库连接,使权限变更立即生效
FLUSH ALL;
权限回收后,发现数据库负载下降,确定问题是由于 数据库A 这个账号的某些查询引起的,此时,由于服务器压力恢复正常,部分用户的访问已经恢复。

接下来就是排查出是哪个服务的问题了,将涉及到的几个服务全部关闭,重新赋予数据库A账号权限

GRANT ALL PRIVILEGES ON database_name.* TO ‘database_name’@‘%’
逐个重启服务,最终在重启服务a之后,数据库压力陡增,确定问题出在这个服务上,此时恢复其他服务。除服务a其他业务功能均已恢复正常。

定位到了服务,但是问题的根本原因还是没有找到,经过大家的讨论,发现对该服务用到的两个表做了字段类型的变更(表字段类型变更,但是 SQL 没有做相应的调整,查询字段类型与数据库中的类型不一致会造成索引失效,无法利用索引来做查询优化),尝试恢复原来的表结构以验证问题是否能够解决

再次重启服务a,一切恢复正常。

可以看到,在问题排查过程中走了很多弯路,原因在于在最开始没有对故障发生前的所有上下文进行梳理,缺乏一些关键的问题排查信息,导致病急乱投医。所以在遇到线上故障没有思路,无法快速解决的时候,一定要沉下心来,纵观全局,收集事故发生前的上下文信息,做出更加明智,正确的决策,减少故障造成的影响。

【原因分析】
数据库 A中两个表中有个字段的类型由 int 调整为 varchar 导致 SQL 中字段类型与数据库不匹配,无法命中索引,产生大量慢查询,数据库压力过大。

【改进措施】

重大上线必须进行全面的方案评审

数据库大表结构变更一定慎之又慎,先在开发、测试环境验证(数据量规模与正式一致)

优化监控机制,对慢查询 SQL 做严重级别分类,严重影响性能的慢查询作为错误报警发出

建立数据库自身保护机制

对服务分级 ,重要服务的运行环境、数据库等做隔离,重点保护

如果故障发生时有过上线行为,则5分钟内找不到故障原因,立刻开始回滚上线

对于大的上线,在上线方案准备时,必须同步规划回滚方案

在排查问题的时候,发现 某个表上建立了很多的索引,其中 idx_is_confirm 这个索引时可以删掉的,删除该索引可以提高数据库的 insert/update 性能。

在建立索引的时候,除了考虑 SQL 中会用到的字段基于 最左前缀匹配 规则之外,还要考虑该字段的基数是否足够大(Cardinality),如果基数很小,建立索引带来的收益就会很小,甚至影响 insert/update 性能,得不偿失,因此建议对于可枚举的字段,不要建立索引。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值