帮助中心/最新通知

质量为本、客户为根、勇于拼搏、务实创新

< 返回文章列表

【服务器相关】异常处理:Mysql update sql不当引起的生产故障及处理记录

发表时间:2025-06-16 03:46:00 小编:主机乐-Yutio

故障表现

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

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

业务背景

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

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



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());
}
}


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生产故障内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


联系我们
返回顶部