mysql死锁和分库分表问题详解

 更新时间:2021年4月15日 15:02  点击:2280

记录生产mysql的问题点。

业务场景与问题描述

请求一个外部接口时,每天的请求量在900万左右。

分为请求项目和回执这两个项目。请求是用来调用外部接口,回执是接收发送的接口。

在发送请求前会先插入数据库。

在请求后,如果接口返回调用失败,会更新数据库状态为失败。

如果发送成功,则会等待上游给出回执消息后,然后更新数据库状态。

而在生产运行过程中,半年出现过两次mysql导致的mq消费者堆积的问题。

问题分析

记录两次不同的原因导致的生产问题及原因分析。

mysql死锁问题

查看mq聚合平台TPS
上生产发现mq数据一直堆积,且不断上升。而TPS仅为30左右,一直上不去。

这就会使mq消费变慢了,导致不断堆积。具体什么原因导致mq一直堆积,需要继续排查。

查看生产服务器日志

查看生产服务器日志,发现有报错dead Lock的错误。

error response from MySQLConnection [node=24, id=277499, threadId=2735941, state=borrowed, closed=false, autocommit=true, host=10.1.10.74, port=3306, database=sep_4, localPort=27744, isClose:false, toBeClose:false, MySQLVersion:5.7.25], err: Deadlock found when trying to get lock; try restarting transaction, code: 1213

具体的sql如下:

update stage set status = 'success',reply_time = '2021-03-07 10:40:11'  where code = '000123' and create_time > '2021-03-03 00:00:00';

也就是说在执行服务时出现了死锁的情况。

具体有多少条以及耗时,在生产服务器看着不直观,于是就让dba将慢sql的语句和耗时查出来。

查出后发现最长的慢sql的耗时长达7780ms。

仔细查看会发现,sql会发现相同的id一个在执行中,一个在Lock Wait状态。

而这慢sql中有大量的Lock Wait状态。

什么原因导致的死锁

mysql使用的数据库引擎时InnoDB。先了解下什么是死锁:

所谓死锁: 是指两个或两个以上的进程在执行过程中,
因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.
此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程.

通过上面的排查可以看出,出现死锁的问题就是:

在执行sql更新一条数据时,会将这一行数据锁定,执行完成后会释放行锁,而没有执行的sql处于Lock Wait状态。

而程序中导致此原因在于,在发送前后和回执时,频繁操作数据库,可能会出现同时操作同一条数据的情况。

所以在执行中就出现了锁等待的情况。

分库分表未带分片键

首先告警的是stage_prod库的CPU飙到了85%。

数据库线程数是否被打满

经过查看数据库连接情况可知,数据库连接数并没有被占满。

查出慢sql和耗时

查出的问题sql:

update stage set status = 'success',reply_time = '2021-03-07 10:40:11'  where create_time > '2021-03-03 00:00:00';

查看sql会发现,这条sql竟然没有带分片键code字段。而这条sql是回执时执行的。

排查生产服务器日志

代码中有做判断,如果code值不为空,sql会带上code的值。那么没带上,就需要查看为何没有带上。

查看代码会发现,code是从redis中获取的,是在发送时set到redis中的。但是没有set进去就很奇怪了。

初步怀疑是redis问题,然后就与redis维护的平台沟通,发现果真是因为redis故障导致的问题。

为什么不带分片键CPU就会飙升

首先公司用的是hotdb分库分表,因为每天的入库量是在900万左右,一个表是上亿条数据。

如果只是单纯用索引,是无法满足要求的。

分库分表hotdb,根据code值做hash分片,做了64个分片。也就是说64个数据库,分布在8台服务器上的16个实例里面。

这样可以避免各分片数据不均,理论上避免了过度集中在某个分片上。

而如果不带分片键code的sql,所有的dml操作全部下发到所有的底层库上进行执行,相当于遍历了一遍库。

这样就可能会导致CPU直接飙到99%,甚至直接导致服务器直接崩掉,这样操作是很可怕的。

解决办法

应急处理:先停掉几台服务减少数据库操作

数据持续堆积,会影响数据处理速度。那么,就要先降低操作的速度,最快速的办法就是停服务,减少数据库的操作频率。

减少数据库操作避免数据库死锁

死锁一般时由于程序上没有控制好dml操作的提交,没有及时提交.

减少重复操作同一条数据。在批量操作时减少每批dml数,保证快速提交,避免长事务,避免重复提交dml。

那么怎样减少操作呢?

合并sql

将发送前插入和发送失败时更新,直接合并到一条sql,这样就可以避免多次操作同一条数据的情况。

批量执行时减少长事务和条数

执行时发现,每次批量执行20条sql,比一次性执行200条的效率更快。

所以尽可能避免这种问题。

每条sql必须带分库分表分片键

原则就是不能因为一条数据就拖累整个数据库的操作速度。

分片键必须带上,如果不带分片键,就抛错。

增加时间区间开闭区间

用code来做分片键,用createTime做分区。那么在保证code存在的情况下,可以写上开闭区间,可以提高执行效率。

更优解:sql顺序执行

这种方案可以通过把将要执行的sql统一发到一个mq来消费执行,这样可以保证sql顺序执行,从而避免死锁的产生。

但是这个需要根据业务场景来区分。

复盘

mysql死锁问题,要尽可能避免频繁操作同一条数据,也要避免长事务;
针对分库分表问题,一定要带上分片键;
监控机制不可少;

总结

到此这篇关于mysql死锁和分库分表问题的文章就介绍到这了,更多相关mysql死锁和分库分表内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • MySQL性能监控软件Nagios的安装及配置教程

    这篇文章主要介绍了MySQL性能监控软件Nagios的安装及配置教程,这里以CentOS操作系统为环境进行演示,需要的朋友可以参考下...2015-12-14
  • 详解Mysql中的JSON系列操作函数

    新版 Mysql 中加入了对 JSON Document 的支持,可以创建 JSON 类型的字段,并有一套函数支持对JSON的查询、修改等操作,下面就实际体验一下...2016-08-23
  • 深入研究mysql中的varchar和limit(容易被忽略的知识)

    为什么标题要起这个名字呢?commen sence指的是那些大家都应该知道的事情,但往往大家又会会略这些东西,或者对这些东西一知半解,今天我总结下自己在mysql中遇到的一些commen sense类型的问题。 ...2015-03-15
  • MySQL 字符串拆分操作(含分隔符的字符串截取)

    这篇文章主要介绍了MySQL 字符串拆分操作(含分隔符的字符串截取),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-22
  • mysql的3种分表方案

    一、先说一下为什么要分表:当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。根据个人经验,mysql执行一个sql的过程如下:1...2014-05-31
  • Windows服务器MySQL中文乱码的解决方法

    我们自己鼓捣mysql时,总免不了会遇到这个问题:插入中文字符出现乱码,虽然这是运维先给配好的环境,但是在自己机子上玩的时候咧,总得知道个一二吧,不然以后如何优雅的吹牛B。...2015-03-15
  • Centos5.5中安装Mysql5.5过程分享

    这几天在centos下装mysql,这里记录一下安装的过程,方便以后查阅Mysql5.5.37安装需要cmake,5.6版本开始都需要cmake来编译,5.5以后的版本应该也要装这个。安装cmake复制代码 代码如下: [root@local ~]# wget http://www.cm...2015-03-15
  • 用VirtualBox构建MySQL测试环境

    宿主机使用网线的时候,客户机在Bridged Adapter模式下,使用Atheros AR8131 PCI-E Gigabit Ethernet Controller上网没问题。 宿主机使用无线的时候,客户机在Bridged Adapter模式下,使用可选项里唯一一个WIFI选项,Microsoft Virtual Wifi Miniport Adapter也无法上网,故弃之。...2013-09-19
  • 忘记MYSQL密码的6种常用解决方法总结

    首先要声明一点,大部分情况下,修改MySQL密码是需要有mysql里的root权限的...2013-09-11
  • MySQL数据库备份还原方法

    MySQL命令行导出数据库: 1,进入MySQL目录下的bin文件夹:cd MySQL中到bin文件夹的目录 如我输入的命令行:cd C:/Program Files/MySQL/MySQL Server 4.1/bin (或者直接将windows的环境变量path中添加该目录) ...2013-09-26
  • Mysql命令大全(详细篇)

    一、连接Mysql格式: mysql -h主机地址 -u用户名 -p用户密码1、连接到本机上的MYSQL。首先打开DOS窗口,然后进入目录mysql/bin,再键入命令mysql -u root -p,回车后提示你输密码.注意用户名前可以有空格也可以没有空格,但是密...2015-11-08
  • Navicat for MySQL 11注册码\激活码汇总

    Navicat for MySQL注册码用来激活 Navicat for MySQL 软件,只要拥有 Navicat 注册码就能激活相应的 Navicat 产品。这篇文章主要介绍了Navicat for MySQL 11注册码\激活码汇总,需要的朋友可以参考下...2020-11-23
  • node.js如何操作MySQL数据库

    这篇文章主要介绍了node.js如何操作MySQL数据库,帮助大家更好的进行web开发,感兴趣的朋友可以了解下...2020-10-29
  • mysql IS NULL使用索引案例讲解

    这篇文章主要介绍了mysql IS NULL使用索引案例讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-14
  • 基于PostgreSQL和mysql数据类型对比兼容

    这篇文章主要介绍了基于PostgreSQL和mysql数据类型对比兼容,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-25
  • RHEL6.5编译安装MySQL5.6.26教程

    一、准备编译环境,安装所需依赖包yum groupinstall 'Development' -y yum install openssl openssl-devel zlib zlib-devel -y yum install readline-devel pcre-devel ncurses-devel bison-devel cmake -y二、编译安...2015-10-21
  • Mysql中 show table status 获取表信息的方法

    这篇文章主要介绍了Mysql中 show table status 获取表信息的方法的相关资料,需要的朋友可以参考下...2016-03-12
  • 20分钟MySQL基础入门

    这篇文章主要为大家分享了20分钟MySQL基础入门教程,快速掌握MySQL基础知识,真正了解MySQL,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-12-02
  • mongodb与mysql命令详细对比

    传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,但是集合中没有列、行和关...2013-09-11
  • Delphi远程连接Mysql的实现方法

    这篇文章主要介绍了Delphi远程连接Mysql的实现方法,需要的朋友可以参考下...2020-06-30