一次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中InnoDB存储引擎的锁的基本使用教程
May 26 MySQL
MySQL中连接查询和子查询的问题
Sep 04 MySQL
SQL注入详解及防范方法
Dec 06 MySQL
面试中老生常谈的MySQL问答集锦夯实基础
Mar 13 MySQL
面试提问mysql一张表到底能存多少数据
Mar 13 MySQL
MySQL读取JSON转换的方式
Mar 18 MySQL
mysql insert 存在即不插入语法说明
Mar 25 MySQL
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
Apr 20 MySQL
提高系统的吞吐量解决数据库重复写入问题
Apr 23 MySQL
mysql 获取相邻数据项
May 11 MySQL
MySQL导致索引失效的几种情况
Jun 25 MySQL
MySQL主从切换的超详细步骤
Jun 28 MySQL
Mysql超详细讲解死锁问题的理解
Nebula Graph解决风控业务实践
MySQL实现配置主从复制项目实践
Mysql多层子查询示例代码(收藏夹案例)
Mar 31 #MySQL
MySQL Server层四个日志的实现
分享几个简单MySQL优化小妙招
MySQL Server 层四个日志
You might like
使用NetBeans + Xdebug调试PHP程序的方法
2011/04/12 PHP
php中PDO方式实现数据库的增删改查
2015/05/17 PHP
JavaScript中:表达式和语句的区别[译]
2012/09/17 Javascript
js二维数组排序的简单示例代码
2014/01/24 Javascript
jQuery学习笔记之总体架构
2014/06/03 Javascript
AngularJS中取消对HTML片段转义的方法例子
2015/01/04 Javascript
整理关于Bootstrap列表组的慕课笔记
2017/03/29 Javascript
Vue.js展示AJAX数据简单示例讲解
2017/03/29 Javascript
nodejs服务搭建教程 nodejs访问本地站点文件
2017/04/07 NodeJs
Bootstrap实现下拉菜单多级联动
2017/11/23 Javascript
echarts整合多个类似option的方法实例
2018/07/10 Javascript
微信小程序日历效果
2018/12/29 Javascript
[03:18]DOTA2放量测试专访820:希望玩家加入国服大家庭
2013/08/25 DOTA
[02:36]DOTA2英雄基础教程 斯拉克
2013/11/29 DOTA
[01:14:55]EG vs Spirit Supermajor 败者组 BO3 第三场 6.4
2018/06/05 DOTA
[47:46]完美世界DOTA2联赛 Magma vs GXR 第三场 11.07
2020/11/10 DOTA
tf.truncated_normal与tf.random_normal的详细用法
2018/03/05 Python
Python数据类型之List列表实例详解
2019/05/08 Python
python之PyQt按钮右键菜单功能的实现代码
2019/08/17 Python
Python字符串、列表、元组、字典、集合的补充实例详解
2019/12/20 Python
使用OpenCV去除面积较小的连通域
2020/07/05 Python
Python爬虫爬取糗事百科段子实例分享
2020/07/31 Python
HearthSong官网:儿童户外玩具、儿童益智玩具
2017/10/16 全球购物
Lime Crime官网:美国一家主打梦幻精灵系的彩妆品牌
2019/03/22 全球购物
毕业生的自我评价分享
2013/12/18 职场文书
个人简历中的自我评价怎么写
2014/01/26 职场文书
企业业务员岗位职责
2014/03/14 职场文书
司机岗位职责说明书
2014/07/29 职场文书
教师党员个人自我剖析材料
2014/09/29 职场文书
班子四风对照检查材料思想汇报
2014/09/29 职场文书
四风问题对照检查整改措施思想报告
2014/10/05 职场文书
2014年爱国卫生工作总结
2014/11/22 职场文书
消防验收申请报告
2015/05/15 职场文书
python 如何在 Matplotlib 中绘制垂直线
2021/04/02 Python
浅谈Redis跟MySQL的双写问题解决方案
2022/02/24 Redis
Python+Matplotlib图像上指定坐标的位置添加文本标签与注释
2022/04/11 Python