记一次数据库锁超时故障排除
登陆服务查看日志信息如下:
org.springframework.dao.CannotAcquireLockException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may involve com.huaba.dao.HbUserExtendMapper.update-Inline
### The error occurred while setting parameters
### SQL: // 省略
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; ]; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.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.$Proxy126.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.$Proxy128.update(Unknown Source)
at com.huaba.service.user.impl.UserServiceImpl.updateUserExtend(UserServiceImpl.java:257)
at com.huaba.service.user.impl.UserServiceImpl$$FastClassBySpringCGLIB$$4b1d279e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
第一反应去百度了下面这个问题:
update-Inline ### The error occurred while setting parameters
通过一篇博文发现可以直接看Cause的内容能精准定位问题,于是又去百度:
Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
又看了几篇,没有找到直接的答案,但是大家更多的讨论都是事务的问题,异常信息也是说mysql事务回滚,具体是什么原因导致事务回滚呢,于是去找DBA,让帮忙查一下。不久,DBA反馈:有三个事务并发导致锁等待超时,并贴出了执行的sql代码,到此问题得到确认。
反观代码,发现在接口的业务层,这条更新语句在资源锁之前执行,并且这个接口没有和前端做防重处理,因此,将此更新语句移到资源锁内部执行,同时在资源锁内部判断是否已经处理过同样的请求并且任务未完结的记录,若有就做重复处理,这样就可以控制这条更新语句不会发生事务并发。