一次Mysql update sql不当引起的生产故障记录


Posted in MySQL onApril 01, 2022

故障表现

  • 一方面 :在阿里云控制台云数据库PolarDB对应的集群管理页面上,在诊断与优化模块里面的一键诊断会话管理中,发现某条update sql 执行时间非常久且非常频繁;

  • 另一方面:业务监控系统中开始不断有业务执行时间发出告警信息提示,且告警的业务数据不断上升,部分操作影响客户使用。

业务背景

由于业务操作涉及到的业务流比较复杂,对纯技术的分享来看,不是重点讨论的话,为了更有利于理解问题发生的原因,使用类比的方式,把复杂的业务类比成如下描述: 有数据库3张表,第一张表t_grandfather (爷表),第二张表为t_father(父表),第三张表t_grandson(子孙表),DDL如下:

CREATE TABLE `t_grandfather ` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `count` int(11) NOT NULL DEFAULT 0 COMMENT '子孙后代数量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爷表';

CREATE TABLE `t_father ` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `grandfather_id` int(11) NOT NULL COMMENT '老爷表id',
  PRIMARY KEY (`id`),
  KEY `idx_grandfather_id` (`grandfather_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='老爸表';

CREATE TABLE `t_grandson` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `grandfather_id` int(11) NOT NULL COMMENT '老爷表id',
  PRIMARY KEY (`id`),
  KEY `idx_grandfather_id` (`grandfather_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='孙子表';

三张表之间的业务逻辑关系为,先生成老爷表,然后这个老爷取很多老婆(业务),会不断的生娃,生一个娃就会生成一张老爸表,同时会更新老爷表的count=count+1,表示新增一个后代了,老爷的老婆(业务)在不断的生娃的时候,之前的生的娃也会有老婆,他们的老婆也会生娃,对老爷来说,就是它有了孙子(产生新的业务数据),那有了孙子之后也需要更新老爷表的count=count+1,表示新增一个后代了,以此类推,子子孙孙无穷尽也(业务数据不断生成) 如下图所示:

一次Mysql update sql不当引起的生产故障记录

祖传代码的逻辑为,只要是t_father表和t_grandson有新增,就去更新t_grandfather。这个逻辑设计上问题不大,不过考虑到孙子表数据量很猛的时候,这里就会出现一个非常严重的性能问题。以下是业务摘取的一部分伪代码

/**
 * 处理 father 的业务
 */
 public void doFatherBusiness  (){
     //do fatherBusiness baba .... 此处省
     // 插入 t_father 表
    if (fatherMapper.inster(father)){
         //update t_grandfather set count=count+1 where id= #{grandfatherId}
         grandfatherMapper.updateCount(father.getGrandfatherId  ())  ;
     }
}


 /**
 * 处理 grandson 的业务
 */
 public void doGrandsonBusiness  (){
     //do grandson baba .... 此处省略
     // 插入 t_grandson 表
     if(grandsonMapper.inster(grandson)){
          //update t_grandfather set count=count+1 where id= #{grandfatherId}
          grandfatherMapper.updateCount(grandson.getGrandfatherId());
     }
}

当多个业务(线程)分别调用上面的方法时,都会对t_grandfather表的更新操作造成巨大的压力,特别是更新同一个id的情况下,mysql server内部对锁的竞争非常激烈。最后表现出来就如前文背景描述的一致。

解决方案

1. 临时处理方案:

一方面,在阿里云控制台,对sql进行限流,在正常阻塞的会话,强制kill掉,让数据的线程不阻塞着,释放资源,另外一方面,在把接收请求的服务减少节点数,目的是减少业务数据量进入;

2. 长久方案

一方面更改掉上面的业务逻辑,插入t_grandson表和t_father表时,不在去更新t_grandfather表的count字段;另一方面,需要用到count统计需求时,全部切换成别的方式;

总结

到此这篇关于一次Mysql update sql不当引起的生产故障的文章就介绍到这了,更多相关Mysql update sql生产故障内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
Mysql Show Profile
Apr 05 MySQL
MySQL 重写查询语句的三种策略
May 10 MySQL
MySQL 查询速度慢的原因
May 25 MySQL
Mysql文件存储图文详解
Jun 01 MySQL
详解MySQL多版本并发控制机制(MVCC)源码
Jun 23 MySQL
SQL实现LeetCode(177.第N高薪水)
Aug 04 MySQL
MySQL连接控制插件介绍
Sep 25 MySQL
mysql5.6主从搭建以及不同步问题详解
Dec 04 MySQL
Mysql忘记密码解决方法
Feb 12 MySQL
Linux系统下MySQL配置主从分离的步骤
Mar 21 MySQL
mysql查找连续出现n次以上的数字
May 11 MySQL
MySQL索引失效场景及解决方案
Jul 23 MySQL
Mysql超详细讲解死锁问题的理解
Nebula Graph解决风控业务实践
MySQL实现配置主从复制项目实践
Mysql多层子查询示例代码(收藏夹案例)
Mar 31 #MySQL
MySQL Server层四个日志的实现
分享几个简单MySQL优化小妙招
MySQL Server 层四个日志
You might like
PHP程序漏洞产生的原因分析与防范方法说明
2014/03/06 PHP
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
网页的标准,IMG不支持onload标签怎么办
2006/06/29 Javascript
JavaScript 学习笔记(六)
2009/12/31 Javascript
老鱼 浅谈javascript面向对象编程
2010/03/04 Javascript
基于jquery的文本框与autocomplete结合使用(asp.net+json)
2012/05/30 Javascript
JavaScript和CSS通过expression实现Table居中显示
2013/06/28 Javascript
ztree实现权限横向显示功能
2017/05/20 Javascript
JavaScript数组_动力节点Java学院整理
2017/06/26 Javascript
JavaScript中递归实现的方法及其区别
2017/09/12 Javascript
React教程之封装一个Portal可复用组件的方法
2018/01/02 Javascript
vue中进入详情页记住滚动位置的方法(keep-alive)
2018/09/21 Javascript
vue-cli配置flexible过程详解
2019/07/04 Javascript
vue setInterval 定时器失效的解决方式
2020/07/30 Javascript
Python爬虫实现获取动态gif格式搞笑图片的方法示例
2018/12/24 Python
PyQt5实现简单数据标注工具
2019/03/18 Python
Python 分享10个PyCharm技巧
2019/07/13 Python
Python 日期区间处理 (本周本月上周上月...)
2019/08/08 Python
python 下 CMake 安装配置 OPENCV 4.1.1的方法
2019/09/30 Python
python多进程(加入进程池)操作常见案例
2019/10/21 Python
python实现opencv+scoket网络实时图传
2020/03/20 Python
jupyter notebook 恢复误删单元格或者历史代码的实现
2020/04/17 Python
PyTorch中torch.tensor与torch.Tensor的区别详解
2020/05/18 Python
纯CSS3代码实现switch滑动开关按钮效果
2016/08/30 HTML / CSS
Willer台湾:日本高速巴士/夜行巴士预约
2017/07/09 全球购物
澳大利亚小众服装品牌:Maurie & Eve
2018/03/27 全球购物
意大利巧克力店:Chocolate Shop
2019/07/24 全球购物
C#如何进行LDAP用户校验
2012/11/21 面试题
领导班子四风问题个人对照检查材料
2014/10/04 职场文书
毕业晚宴祝酒词
2015/08/11 职场文书
Python - 10行代码集2000张美女图
2021/05/23 Python
Python利用机器学习算法实现垃圾邮件的识别
2021/06/28 Python
ObjectMapper 如何忽略字段大小写
2021/06/29 Java/Android
MongoDB数据库部署环境准备及使用介绍
2022/03/21 MongoDB
20180830晚上第一届KSL半决赛 雨神vs解冻(二龙 三炮解说)
2022/04/01 星际争霸
Hive日期格式转换方法总结
2022/06/25 数据库