记一次生产环境mysql锁表问题的处理

1.生产环境mysql导致的多表被锁表情况
故事是这样的:一天,运维人员突然找到身为开发的我,说某某业务出问题了,本着让运维人员能更好熟悉业务,更快成长的原则。
我问了句:“出了啥问题?”
运维同事::”***业务订单报文没有推送成功."
我又问了句:“日志看了没?”
运维同事::”…日志在哪里?"
。。。。。。
运维同事::”日志没看到有问题,都打印了!"
我一脸懵逼,正常执行怎么还出问题:“日志没有问题么?”
。。。。。。
我就不信这个邪了,日志正常怎么会程序业务没完成。

无奈自己上手看问题吧:
先看页面业务:这个业务好像卡在了最终的流程归档的步骤,类似这样的流程:只不过是卡在了归档的步骤。既然卡了就会有原因的,查到这个订单的执行线程看下应该就能发现问题。
在这里插入图片描述
归档模块的日志:si_order模块:
在这里插入图片描述
在这里插入图片描述
打开一看:我尼玛,这也叫日志正常啊,运维这厮还是成长的不到位啊,此处省略喷人一万字…算了,让他自己耗子尾汁吧。

Lock wait timeout exceeded; try restarting transaction:锁等待超时了

Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:262)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
	at com.sun.proxy.$Proxy93.update(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:63)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
	at com.sun.proxy.$Proxy94.updateStatusByOrder(Unknown Source)
	at com.si.service.impl.OrderServiceImpl.operateDcprQueue(OrderServiceImpl.java:1425)
	at com.si.service.impl.OrderServiceImpl$$FastClassBySpringCGLIB$$a267b731.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at com.si.config.DataSourceAspect.around(DataSourceAspect.java:61)
	at sun.reflect.GeneratedMethodAccessor83.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

2.问题来了,为什么会发生锁等待超时的问题?难道锁表了么?
因为si_order模块不影响客户页面的操作,是属于用户感知不到的模块。于是,决定把si_order模块停了,把锁释放调,等一会再重启,于是说干就干。
果然,这样操作以后,order模块重启以后报错少了很多,问题貌似解决了。

3.但是,不过几分钟后,又出现问题了,还是之前的锁超时问题
无奈,看样子和order模块的问题关系不是很大呀,排查问题把,根据日志找到执行的sql语句,再到代码中查看sql调用的地方,果然,这个sql还有别的模块在调用,定时任务模块。打开日志一看,日志一堆报错。会不会是定时任务模块导致的问题呢?
定时任务模块日志:
在这里插入图片描述

好了,定时任务模块也不影响用户感知,重启试试吧!因为业务代码不知道是干啥的,写这块的人早已离职,也懒得去研究他的业务了,哈哈。。。。。。
这种很鸡贼的解决问题方式并不推荐哈…
于是,在中午午休期间,将定时任务模块重启了…一会以后,oder模块不再报锁等待超时了,之前没有完成的业务订单也顺利归档了。问题解决,定时任务模块重启,也没有报错了,问题就这样接化发了。。。。

4.锁等待超时的处理
上面停模块的方法只是一时管用,并不能治本,所以,为了能在以后避免再次出现这样的问题,一定要仔细分析业务中的代码,是否存在同时操作的可能性,或者sql冲突的问题。这样才能治标治本。
如果模块不能手动结束,我们还可以手动结束锁等待的sql语句线程:

-- 行级死锁定位: 查询到trx_mysql_thread_id 然后kill掉;
SELECT * from information_schema.INNODB_TRX;
SELECT trx_mysql_thread_id from information_schema.INNODB_TRX;
kill ***;

如图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37488998/article/details/110229948