数据库宕机案例,生产真实案例复盘

1,493 阅读5分钟

前言

事故发生在20221104,当晚动作为注册中心升级,结果导致数据库宕机,造成生产环境影响4小时,由于中间有二十大,所以给出了技术方案,但一直没动,直到20221207才完全修复。

技术架构

本系统为自研注册中心,启动流程如下:

  1. 服务启动,从数据库里拉取全量权限数据,并把数据放到redis里;
  2. 注册中心根据日志主动去call提供者,查看是否还在,以防止把不正确的提供者地址返回给消费者;

消费者消费流程如下:

  1. 先与F5建立连接,F5负载均衡到注册中心;
  2. 注册中心拿dubbo://...里面的数据去redis里查看,查到有权限就返回提供者,如果没有权限就返回无权限;
  3. 当提供者和消费者提交申请并提供者和注册中心都同意时,会去更新redis里的缓存;

PS:redis之前出现过问题,具体发生了啥可以看dubbo注册中心问题,生产真实案例复盘

当晚发生了啥

21:30,通知所有开发者注册中心开始升级,20台机器依次重启(因为性能问题,没用docker,k8s那些东西,要手动启动tomcat),花了差不多45分钟

22:00,所有消费者权限通过,开始重新发布、订阅

事故开始

22:10,有业务开发表示,注册中心的管理页面登录超时,我们这个页面只对内部开发使用,所以是直接查数据库,当时判断是数据库卡了一下,毕竟之前就有过select * from 表名 where 带索引的主键id = ?这么一个sql跑了10分钟的事(PS:这个bug还在处理,下一篇文章就写这个了)

22:15,最后一台注册中心重启完毕,但消费者表示,错误的提供者数据返回给了他们

22:17,运维和我讲,数据库不太正常(当时的图找不到了,就找了一个后期的),注意连接数,20台机器,最低1500个连接数,也就是说平均一台75个,有系统调优经验的都能看出来,这数量绝对不对

image.png

22:30,主库进行2次扩容后发生宕机,备库启动,扛了一会备库宕机,数据库组件宕机,但这时业务那边开始大批量启动,产生了许多垃圾数据

05:00,临时改了代码,服务器启动时不会去数据库里拿,redis里的数据本地跑脚本去更新,这才启动起来

事故分析

排查阶段一

数据库连接数这么多,首先mybatis线程池100%是肯定的,减小最多线程数就好,但为啥会这么高?

连接数这么高,代表队列里有很多任务在等待执行,也就是说在执行的sql太慢了,那就是慢sql,效果有些好转。

排查阶段二

ok,数据库慢sql导致的解决了,但以后还会出问题,所以要对连接池大小进行处理,大家设置时可能根据感觉、经验去设置,这次为了保险起见我们找DBA,TA进行压测和评估后设置,提高核心线程数,降低最大线程数。

排查阶段三(超级亮点,超级大坑!!!)

代码改好了,开始进行压测,忽然发现有几次数据库连接莫名其妙的还是会上去,之前的排查已经相当到位了,那问题还会出现在哪里呢???

执行

select connection_id() from dual;

发现,有一堆事务!!!不可能啊,从数据库里拉出来数据,再放到redis里,撑死200个,但查出来几千个,绝对有问题,后面就要看当时都在做什么事,会这么多。

当时所有动作:

  1. 注册从数据库拉出来数据,放到redis里(已排查)
  2. 监控页面上点点点(不可能有人能点暴数据库把)
  3. 服务调用时,发送日志给监控中心,监控中心存储到hbase

好了,现在第三点最可以,然后去看代码直接一个大震惊!!!

QQ截图20221214172103.png

你没有看错,Transactional事务注解,直接加到了类上面,但代码里对数据库没有进行任何操作。那为什么对hbase进行事务操作,数据库会有影响???

以下内容截图自CSDN

@Transactional的实现原理
该注解是通过JDBC的事务 + Spring的AOP动态代理来完成的.
1、 事务开始时,通过AOP机制,生成一个代理connection对象,
2、 并将其放入 DataSource 实例的某个与 DataSourceTransactionManager 相关的某处容器中。
3、 在接下来的整个事务中,客户代码都应该使用该 connection 连接数据库,
4、 执行所有数据库命令。
5、 事务结束时,回滚在第1步骤中得到的代理 connection 对象上执行的数据库命令,
6、 然后关闭该代理 connection 对象

请注意,根据jdbc事务和aop完成......

也就是说,只要加了Transactional,就算里面拉坨屎,数据库都会上个事务!!!

问题解决

总结

事务不能乱加!!!

事务不能乱加!!!

事务不能乱加!!!