数据库事务的几个特性:A(原子性)C(一致性)I(隔离性)D(持久性),即ACID原则
从1-4,数字越大,并发能力越低
1、读未提交
该隔离级别下的事务会读到其他未提交事务的数据,此现象也成为脏读;
2、读已提交
一个事务可以读取另一个已提交的事务,多次读会造成不一样的结果,此现象称为不可重复读问题;Oracle和SQL Server的默认隔离级别
3、可重复读
是MySQL默认的隔离级别,在同一个事务里,只要未结束,读到的都是一致的,就算外面把数据删了,还是一致的;但是,会有幻读现象;MySQL的InnoDB引擎是通过next-key locks机制来避免幻读的;
4、序列化
在该隔离级别下,事物都是串行执行的,几乎没有任何并发能力了;MySQL数据库的InnoDB引擎会给读操作隐式加一把共享锁,从而避免脏读、不可重复读和幻读问题;
在spring中设置
@Transactional(isolation = Isolation.DEFAULT)
所有的隔离级别
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
private final int value;
private Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
在spring中设置
@Transactional(propagation = Propagation.REQUIRED )
所有传播行为
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
同一对象内事务方法互调默认失效,原因:绕过了代理对象,相当于代码复制粘贴;
因为事务底层基于AOP实现,所以事务机制只对代理对象起作用,而对普通对象不会起作用;
1、Spring事务底层是怎么工作的?
切面逻辑,在事务管理器里面创建数据库连接,避免每条语句创建数据库连接,这样的话这多条语句就不是在一个事务里面了;之后会把自动提交设置为false,conn.autocommit=false;在后面进行提交或回滚,conn.commit(),conn.rollback();
2、同类方法调用为什么会事务失效?
相当于是普通对象,即UserService同类方法调用a()方法,就相当于new UserService().a();这是一个普通对象,不是代理对象,直接忽视了事务注解,因为只有UserService的代理对象才会管你的事务注解;
3、解决方案:使用代理对象来调用事务方法
(1)引入aop-starter:引入了aspectj;
(2)@EnableAspectJAutoProxy(exposeProxy=true):开启aspectj动态代理功能,以后所有的动态代理都是aspectj帮我们创建的,即使没有接口也可以;exposeProxy=true对外暴露代理对象
(3)本类互调调用对象
public void a(){
OrderServiceImpl orderService = (OrderServiceImpl)AopContext.currentProxy();
orderService.b();
orderService.c();
}
本文完!!!希望能对你有所帮助!!!