表锁死问题以及事务回滚等问题

在项目中遇到因为事务没有结束,导致插入表的操作将表给锁住了,关于这个表的其他接口也无法访问了。

 

解决过程:(救急解决)

在mysql新建查询

show processlist;

找到超时的sql语句,找对应线程

通过kill该线程

kill trx_mysql_thread_id

后期解决:

通过查看tomcat日志发现是某个接口里面发出http请求一直未收到响应,导致事务一直未结束,也导致该事务中的表被锁死。然后将该http请求放到线程中异步处理,解决了事务处理超时问题。应该也可以通过设置innodb_lock_wait_timeout的大小进行控制超时的时长(本人没有实验,查看资料,感觉应该可以)

 

在搜索表锁死的问题看到了一些关于事务回滚的问题(虽然没有遇到,但是也做一下小结)

如果将service的内部私有方法加上注解@Transational,并不能将该方法设为一个事务,事务不会回滚,因为Spring框架里面的事务是通过动态代理实现的,如果是内部私有方法只是该类的内部实例,并不在Spring的工厂里面,只有在外部被调用时,才会生成动态代理,所以也不会实现aop切面代码。

MySQL死锁导致未回滚

查看参数  innodb_rollback_on_timeout

show VARIABLES like 'innodb_rollback_on_timeout'

如果 innodb_rollback_on_timeout为ON,那么事务超时后将导致InnoDB终止并回滚整个事务;如果 innodb_rollback_on_timeout为OFF,那么事务超时后只回滚事务超时的最后一条语句。

嵌套事务

嵌套事务即内部,外部都有事务(如果有try catch但是没有把异常给扔出去)

  1. 内外都无try catch,事务正常回滚
  2. 外部try catch,内部异常,正常回滚,外部异常,回滚失败
  3. 内部有try catch,内部异常,回滚失败,外部异常,正常回滚
  4. 内外都有try catch,内部和外部异常,回滚都失败

正确做法是异常一定要抛出RuntimeException

事务的传播行为

事务传播行为类型 说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与

PROPAGATION_REQUIRED类 似的操作。

 

展开阅读全文

没有更多推荐了,返回首页