一次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之DML语言
Apr 05 MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 MySQL
mysql数据库入门第一步之创建表
May 14 MySQL
MySQL为id选择合适的数据类型
Jun 07 MySQL
解决Mysql的left join无效及使用的注意事项说明
Jul 01 MySQL
MySQL系列之开篇 MySQL关系型数据库基础概念
Jul 02 MySQL
MySQL子查询中order by不生效问题的解决方法
Aug 02 MySQL
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
Aug 23 MySQL
MySQL七大JOIN的具体使用
Feb 28 MySQL
mysql的单列多值存储实例详解
Apr 05 MySQL
进阶篇之linux环境下安装MySQL数据库
Apr 09 MySQL
MySQL索引失效十种场景与优化方案
May 08 MySQL
Mysql超详细讲解死锁问题的理解
Nebula Graph解决风控业务实践
MySQL实现配置主从复制项目实践
Mysql多层子查询示例代码(收藏夹案例)
Mar 31 #MySQL
MySQL Server层四个日志的实现
分享几个简单MySQL优化小妙招
MySQL Server 层四个日志
You might like
让你的PHP同时支持GIF、png、JPEG
2006/10/09 PHP
php中switch语句用法详解
2015/08/17 PHP
PHP二维数组排序简单实现方法
2016/02/14 PHP
php实现网页端验证码功能
2017/07/11 PHP
js 调整select 位置的函数
2008/02/21 Javascript
actionscript与javascript的区别
2011/05/25 Javascript
根据经纬度计算地球上两点之间的距离js实现代码
2013/03/05 Javascript
jquery实现table鼠标经过变色代码
2013/09/25 Javascript
Js参数值中含有单引号或双引号问题的解决方法
2013/11/06 Javascript
使用JQuery快速实现Tab的AJAX动态载入(实例讲解)
2013/12/11 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
2014/01/15 Javascript
JS利用cookie记忆当前位置的防刷新导航效果
2015/10/15 Javascript
javascript瀑布流布局实现方法详解
2016/02/17 Javascript
js截取字符串功能的实现方法
2017/09/27 Javascript
Ant Design Vue table中列超长显示...并加提示语的实例
2020/10/31 Javascript
python中使用smtplib和email模块发送邮件实例
2014/04/22 Python
Python脚本在Appium库上对移动应用实现自动化测试
2015/04/17 Python
python for 循环获取index索引的方法
2019/02/01 Python
浅谈spring boot 集成 log4j 解决与logback冲突的问题
2020/02/20 Python
python数据库编程 Mysql实现通讯录
2020/03/27 Python
Python 程序报错崩溃后如何倒回到崩溃的位置(推荐)
2020/06/23 Python
浅谈python处理json和redis hash的坑
2020/07/16 Python
详解Selenium-webdriver绕开反爬虫机制的4种方法
2020/10/28 Python
Python plt 利用subplot 实现在一张画布同时画多张图
2021/02/26 Python
在C语言中实现抽象数据类型什么方法最好
2014/06/26 面试题
银行实习生的自我评价
2013/12/09 职场文书
个人承诺书怎么写
2014/05/24 职场文书
化学工程专业求职信
2014/08/10 职场文书
党员个人整改措施
2014/10/24 职场文书
自荐信格式范文
2015/03/04 职场文书
搞笑婚礼主持词开场白
2015/11/24 职场文书
关于应聘教师的自荐信
2016/01/28 职场文书
创业计划书之婴幼儿游泳馆
2019/09/11 职场文书
html输入两个数实现加减乘除功能
2021/07/01 HTML / CSS
【海涛七七解说】DCG第二周:DK VS 天禄
2022/04/01 DOTA
用Python仅20行代码编写一个简单的端口扫描器
2022/04/08 Python