目录
一、事务的四个特征ACID
A:Atomicity原子性
C:Consistanty一致性
I:ISolation隔离性
D:Durability持续性
二、mysql的四种隔离级别
其中mysql的四种隔离级别分别是:Read uncommitted(读未提交)、Read committed(读已提交)、Repeatable read(可重复读)、Serializable(序列化)。
1.Read uncommitted:
读取了还未提交的数据,会导致脏读
2.Read committed:
1)能够确保只读取已提交的东西。
2)大部分数据库的默认隔离级别,如sql server、oracle
3)可能会出现不可重复读,即同一个事务多次查询中可能会不同,因为在该事务得其他实例在该实例处理期间,其他实例可能对数据做了新的改动提交,导致多次select结果不一致。
3.Repeatable read:
1)能保证一个事务的多个实例并发读取时看到的结果是一致的,即可重复读取。
2)mysql数据库的默认隔离级别。
3)可能出现幻读,即一个事务在读取数据时,另一个事务在该范围内的插入了其他行,导致再读取该范围的数据时,出现不一致。
4.Serializable:
1)序列化读取,最严格的隔离级别。强制事务排序,在每行数据上加共享锁。
2)可能导致大量的超时和锁竞争
三、脏读、不可重复读和幻读现象的解释
隔离级别\现象 | 脏读 | 不可重复读 | 幻读 |
Read uncommitted | 有 | 有 | 有 |
Read committed | 无 | 有 | 有 |
Repeatable read | 无 | 无 | 有 |
Serializable | 无 | 无 | 无 |
1.脏读
读取了其他事务尚未提交的数据
2.不可重复读
一个事务第二次读取数据时,另一个事务对这些数据做了更新,导致两次结果不一致
3.幻读
一个事务第二次读取数据时,另一个事务在该查询范围内提交了新的数据,导致两次读取数量不一致
四、5种状态
1. 活动状态
事务在执行时的状态叫活动状态。
2. 部分提交状态
事务中最后一条语句被执行后的状态叫部分提交状态。
3. 失败状态
事务不能正常执行的状态叫失败状态。
4. 提交状态
事务在部分提交后,将往硬盘上写入数据,当最后一条信息写入后的状态叫提交状态。进入提交状态的事务就成功完成了。
5. 中止状态
事务回滚并且数据库已经恢复到事务开始执行前的状态叫中止状态。
五、事务的传播特性
1.几种传播特性
PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启;
2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行;
3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常;
4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起;
5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务;
6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常;
7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。
2.需要注意几点
1.Spring的@Transaction配置可以在controller,service和dao层的类上声明,但是如果在方法上声明,只对public的方法生效,这是由于spring代理决定的
2.类内部方法自调用,不会触发传播机制,如下,不会触发method2的事务声明,即method2的事务声明无效
class A {
public void method1() {
method2();
}
@Transactional
public void method2() {
}
}
3.传播特性实例
1)A调用B,A无事务,B有事务,则B能正常执行成功,A失败
class A {
public void method1() {
method2();
dao.deleteById(1)
}
}
class B {
@Transactional
public void method2() {
dao.deleteById(2)
}
}
2)方法1调用方法2,均配置事务,若成功都成功,若失败都失败回滚
class A {
@Transaction
public void method1() {
method2();
dao.deleteById(1)
}
}
class B {
@Transactional
public void method2() {
dao.deleteById(2)
}
}
3)方法1默认事务传播特性,方法2为REQUIRES_NEW。若1和2的异常均各自catch,则事务相互独立,1,2均能各自提交成功。否则,如果2的异常影响1,则若2失败,全部失败。如果1异常,2正常,如果1的异常不给catch,也全部回滚,如果1的异常被catch,则2能正常提交。
class A {
@Transaction
public void method1() {
try{
dao.deleteById(1)
}catch(Exception e){
}
try{
method2();
}catch(Exception e){
}
}
}
class B {
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void method2() {
try{
dao.deleteById(2)
}catch(Exception e){
}
}
}
4)嵌套事务,JpaDialect不支持savepoint,所以没做过多验证,根据其他大神验证的结果是,外部事务失败影响内部,内部失败不影响外部。即内部事务回滚不会导致外部事务回滚,外部事务回滚会导致内部事务回滚。
参考:https://www.cnblogs.com/protected/p/6526857.html
http://blog.chinaunix.net/uid-7345847-id-2643947.html
https://blog.csdn.net/chudaxiakkk/article/details/80889494
https://blog.csdn.net/spyunknow/article/details/105666744