Spring7种传播行为
一. 数据库事务
概念:数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
性质:
(1)原子性(Atomicity):
事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
(2)一致性(Consistency):
几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
(3)夺隔离性(Isolation):
事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
(4)夺持久性(Durability):
对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。
事务的ACID特性是由关系数据库系统(DBMS)来实现的,DBMS采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所作的更新,如果某个事务在执行过程中发生错误,就可以根据日志撤销事务对数据库已做的更新,使得数据库同滚到执行事务前的初始状态。
对于事务的隔离性,DBMS是采用锁机制来实现的。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
以上源自于百度词条
数据库操作里面如何保证事务的原子性的
为了实现原子性,需要通过日志:将所有对数据的更新操作都写入日志,如果一个事务中的一部分操作已经成功,但以后的操作,由于断电/系统崩溃/其它的软硬件错误而无法继续,则通过回溯日志,将已经执行成功的操作撤销,从而达到“全部操作失败”的目的。最常见的场景是,数据库系统崩溃后重启,此时数据库处于不一致的状态,必须先执行一个crash
recovery的过程:读取日志进行REDO(重演将所有已经执行成功但尚未写入到磁盘的操作,保证持久性),再对所有到崩溃时尚未成功提交的事务进行UNDO(撤销所有执行了一部分但尚未提交的操作,保证原子性)。crash
recovery结束后,数据库恢复到一致性状态,可以继续被使用
说完了事务的特性下面分析数据库在不考虑事务的隔离性的情况下的情况
二.数据库的隔离级别
(1) 脏读
读到了没有提交的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bXhP2FD9-1585293592687)(file:///C:\Users\SFF\AppData\Local\Temp\ksohtml188192\wps1.jpg)]
解读:老板以前就是给小明发500的工资,突然小手一抖打错了变成了1000,正在这个时候小明刚刚好 看到了工资是1000 非常的开心 然后老板那边打错了吗 又改回来了 最后呢小明到手的工资还是500,确实读到了1000,这就是读到了没有提交的数据,也叫脏数据
(2) 不可重复读
在一个事务里面两次读取读取到的数据不一样
不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。
不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4z846AP-1585293592689)(file:///C:\Users\SFF\AppData\Local\Temp\ksohtml188192\wps2.jpg)]
举例子; 小明去超市,买东西,一看卡里还有500块钱,美滋滋,然后去购物,不料这个时候他的媳妇用它的卡消费了500块,小明买好东西回来支付,一看没钱了;
(3) 幻读/虚读
幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WKpQQijW-1585293592689)(file:///C:\Users\SFF\AppData\Local\Temp\ksohtml188192\wps3.jpg)]
小明媳妇对小明的工资卡没收工资;不料小明公司有发给小明一张卡 卡里面500块钱,回头小明媳妇一看小明还有500块钱的一张卡,发现自己出现了幻读………………………………………
现在来看看MySQL数据库为我们提供的四种隔离级别:
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f5sCwUGV-1585293592690)(file:///C:\Users\SFF\AppData\Local\Temp\ksohtml188192\wps4.jpg)]
三. Spring 事务
(1)propagation_requierd:
如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是Spring默认的选择。
(2)propagation_supports:
支持当前事务,如果没有当前事务,就以非事务方法执行。
(3)propagation_mandatory:
使用当前事务,如果没有当前事务,就抛出异常。
(4)propagation_required_new:
新建事务,如果当前存在事务,把当前事务挂起。
(5)propagation_not_supported:
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
(6)propagation_never:
以非事务方式执行操作,如果当前事务存在则抛出异常。
(7)propagation_nested
:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
* 事务管理器
*/
@AliasFor("transactionManager")
String value() default "";
/**
* @see #value
*/
@AliasFor("value")
String transactionManager() default "";
/**
* The transaction propagation type.事务的传播行为
*/
Propagation propagation() default Propagation.REQUIRED;
/**
* The transaction isolation level 事务的隔离级别
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* The timeout for this transaction (in seconds). 事务的超时时间
*/
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/**
* A boolean flag that can be set to {@code true} if the transaction is
* effectively read-only, allowing for corresponding optimizations at runtime.
* 是否是只读属性
*/
boolean readOnly() default false;
/**
* 什么异常才回滚 ==>类名.class
*/
Class<? extends Throwable>[] rollbackFor() default {};
/**
* 那种异常类和它的子类回滚 ==> 字符串
*/
String[] rollbackForClassName() default {};
/**
* 什么异常 <不> 回滚 ==>类名.class
*/
Class<? extends Throwable>[] noRollbackFor() default {};
/**
* 那种异常类和它的子类 <不> 回滚 ==> 字符串
*/
String[] noRollbackForClassName() default {};
本节;
/**
* The transaction propagation type.事务的传播行为
*/
Propagation propagation() default Propagation.REQUIRED;
public enum Propagation {
/**
* Support a current transaction, create a new one if none exists.
* 支持当前事务,如果不存在则创建一个新事务
*/
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
/**
* Support a current transaction, execute non-transactionally if none exists.
* 支持当前事务,如果不存在则非事务执行
*/
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
/**
* Support a current transaction, throw an exception if none exists.
* Analogous to EJB transaction attribute of the same name.
* 使用当前事务,如果没有当前事务,就抛出异常
*/
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
/**
* Create a new transaction, and suspend the current transaction if one exists.
* Analogous to the EJB transaction attribute of the same name.
* 创建一个新的事务,并暂停当前事务(如果存在)
*/
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
/**
* Execute non-transactionally, suspend the current transaction if one exists.
* Analogous to EJB transaction attribute of the same name.
* 非事务执行,如果存在当前事务,则挂起当前事务
*/
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
/**
* Execute non-transactionally, throw an exception if a transaction exists.
* Analogous to EJB transaction attribute of the same name.
* 非事务执行,如果存在事务,则引发异常。类似于同名的EJB事务属性。
*/
NEVER(TransactionDefinition.PROPAGATION_NEVER),
/**
*如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作。
*/
NESTED(TransactionDefinition.PROPAGATION_NESTED);
private final int value;
Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
使用场景
//待完成