热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mysql没索引怎么加锁_MySQL语句优化未加索引导致锁冲突

大概过程在测试环境Docker容器中,在跨进程调用服务的时候,A应用通过Dubbo调用B应用的RPC接口,发现B应用接口超时错误ÿ

大概过程

在测试环境Docker容器中,在跨进程调用服务的时候,A应用通过Dubbo调用B应用的RPC接口,发现B应用接口超时错误,接着通过debug和日志,发现具体耗时的地方在于一句简单SQL执行,但是耗时超过1000ms。

通过查看数据库的进程列表,发现是有死锁锁表了,很多进程状态status处于'sending data',最后为锁住的表添加索引,并且kill掉阻塞的请求,解除死锁,服务速度恢复正常。

下面记录的是跟祥哥一起的大致排查过程:

通过观察业务代码,确认没有内存溢出或者其它事务问题,于是只能考虑Docker环境的数据库和jvm底层详情了。

使用Druid监控SQL执行状态

通过日志,发现有一句SQL严重超时,一句简单SQL,原本是批量插入多条记录,为了定位问题,测试时Mybatis只插入一条记录,但即便如此,还是耗时10秒

format,png

于是打算使用阿里巴巴的数据库连接池Druid进行监控,这篇文章有教如何使用Druid监控SQL执行状态,监控SQL效果如下:

format,png

在SQL监控Tab中,可以看到执行SQL的具体情况,包括某条SQL语句执行的时间(平均、最慢)、SQL执行次数、SQL执行出错的次数等

上面显示的是正常情况下,时间单位是ms,正常的SQL一般在10ms之内,数据量大的控制在30ms之内,这样用户的使用体验感才会良好。所以说之前的1000ms,是不可接受的结果。

通过JMC远程监控Tomcat

JMC(java mission control)是jdk自带的一个监控工具,在jdk的bin目录下(java大法好,该目录下有很多实用的工具)。

为了简单,我加了一个tomcat无验证模式:

#在tomcat的conf目录下的catalina.sh增加如下java启动参数:

-Dcom.sun.management.jmxremote=true

-Dcom.sun.management.jmxremote.port=8888

-Dcom.sun.management.jmxremote.ssl=false

-Dcom.sun.management.jmxremote.authenticate=false

-XX:+UnlockCommercialFeatures -XX:+FlightRecorder

下面是自己本地调试的截图

format,png

然后打开jmc,创建一个JMX连接,输入对应的ip和JMX端口。接着可以设定一段时间内的飞行监控,监测这一分钟内jvm具体参数

当时调试的时候,发现内存使用、CPU占用率、线程状态也挺正常的,没有发现明显的异常错误,效果如下图:

format,png

唯一比较耗时的是在代码tab页中,当时发现了大量的I/O,比上图的比例还高,当时大概占了80%,查看调用树,很多循环tcp socket连接,考虑到应用中本来就有很多需要io以及netty也需要tcp连接,所以大概排除了jvm虚拟机的问题,然后就去排查MySQL的问题。

排查MySQL

在了解MySQL锁概念的时候,可以参考这篇文章mysql什么情况下会触发表锁,由于现在使用的比较多的是InnoDB,所以可以着重看看InnoDB锁问题。

直接执行SQL语句

通过DEBUG代码,从mybatis中取出映射后的SQL语句,在MySQL客户款直接执行SQL和Explain查看执行计划,速度都很快,排除了SQL语句的问题。

查看MySQL线程列表

show processlist;

format,png

从图中可以看出,有些线程的状态处于sending data,查阅资料:所谓的“Sending data”并不是单纯的发送数据,而是包括“收集 + 发送 数据”。

然后后面一列info显示的是具体信息,是查询用来生成主键ID的函数,之前速度都很快,为啥突然就这么慢呢,于是回过头去查看该函数:

select next_value into ret_val from `xxx` where table_name=tableName for update;

update `xxx` set

current_value=current_value+step,

next_value=next_value+step

where table_name=tableName;

select for update,给这个表加了排它锁,阻止其它事务取得相同数据集的共享读锁和排他写锁,同时,这个序列表表中,用来检索的字段没有加索引,在InnoDB行锁机制中:

format,png

由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键(在我们的场景中,就是查询时用到的table_name),是会出现锁冲突的

所以祥哥了解到其它团队因为查询这个表产生事务问题,造成死锁,这个序列表被锁住了。

由于这个自增序列表每个团队都在使用,所以当时测试环境中,经常有dao层超时错误,最终祥哥将这些阻塞的线程kill掉,为序列表加了索引,解决了问题。

小结

下次遇到MySQL执行耗时的情况,排除了代码问题之后,要去看数据库是否有死锁的情况存在,观察有没有被阻塞的线程,排查被阻塞的线程具体info,定位到具体问题。



推荐阅读
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 标题: ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • POCOCLibraies属于功能广泛、轻量级别的开源框架库,它拥有媲美Boost库的功能以及较小的体积广泛应用在物联网平台、工业自动化等领域。POCOCLibrai ... [详细]
  • pc电脑如何投屏到电视?DLNA主要步骤通过DLNA连接,使用WindowsMediaPlayer的流媒体播放举例:电脑和电视机都是连接的 ... [详细]
author-avatar
我只记得她
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有