本文已参与「新人创作礼」活动,一起开启掘金创作之路。
事务
1、事务的隔离级别
- read-uncommited 读未提交(会带来的问题:脏读,重复读、幻读)
- read-commited 读已提交(避免脏读)
- repeatable-read 可重复读(避免脏读和重复度)
- searilizedable 串行的(相当于单线程,可以解决所有问题,但是慢)
2、事务的传播机制
- require 创建新的事务
- require-new 创建新的事务
- nested 嵌套事务
- never 永远不需要当前存在事务
3、事务应用
spring中一般在需要控制事务的地方使用声明式事务或者编程时事务。
声明式事务:@Trancation 编程式事务: 1、PlatformTrancationManager 2、TrancationManagerTemplate
4、事务传播机制的实际使用案例
一般都是在Service类上添加注解@Trancation. 有时需要在一个事务中添加一个新事务用来做单独提交,这里需要指定事务传播机制Require_new
5、事务失效的场景
- 添加事务注解的类不是由spring托管的
- 添加事务的方法不是public修饰的,因为事务时基于aop实现的,aop是利用cglib的代理技术来实现的,如果不是指定public,将没有权限操作类,也就是生成不了代理类。
- 添加事务的方法,异常被捕获
- 添加事务的方法抛出的是检查异常(检查异常:FileNotFoundException, SqlException,IOException等)
- 自定义切面顺序导致失效
- 用final修饰的方法 原因:还是代理的原因,如果用final修饰了,代理类不能重写方法织入事务代码
- 用static修饰的方法 原因同上
- 多线程下事务失效,原因是数据库连接是放在ThradLocal中的,多线程下获取的connect是不一样的。
- 错误的指定传播机制 比如制定了never
- 使用的数据库不支持事务,比如mysql的myIsam引擎
- 数据源没有配置事务管理器
综上:事务失效其实就是两点 1、aop不能正常织入的、代码执行异常引发的。
6、@Trancation是在什么时候开启的事务
真正的开启事务是在执行第一个sql的时候开启的
7、事务使用不当遇到的问题
- 事务设置过大
这是一个真实的故事,充值如果遇到问题,需要做补到账处理,因担心中途处理发生异常,所以加了事务注解,以便回滚,结果没想到来了五十万用户要做补处理,由于数据都在一个事务中处理,所以第一个用户和最后一个用户其实是一起提交事务的,因此用户觉得到账慢,引起投诉,之后就有了图片中的故事。
8、数据库中事务编号查询
SELECT * FROM information_schema.INNODB_TRX;