Spring Boot transaction propagation mechanism level/type/behavior, nested transaction, transaction isolation mechanism

First of all? The propagation behavior of the transaction is for the "nested transaction" question?

Let me talk about the level/type of Spring propagation mechanism,

~七种:事务传播机制/行为 ~					 ~五类:事务隔离级别
 - Required(adj. 必需的)|默认          	   -Default(v. 不履行)默认
 - Requires_new(vt. 需要New)			       -Read_Uncommitted(读未提交)
 - Mandatory(adj. 强制的)				   -Read_Committed(读已提交)
 - Supports(v. 支持)				           -Repeatable_Read(可重复读)
 - Ont_Supported(adj. 不支持的)			   -Serializable(串行化)
 - Never(adv. 从未)
 - Nested(adj. 嵌套的,内装的)

==源码段
@Transactional()
{
    
    
/*默认-事务传播机制/行为 */
Propagation propagation() default Propagation.REQUIRED;
/** 默认 Required 行为
  * ·该传播机制指:<标注事务注解的方法体:·正在使用一个事务,则同加入当前事务中;
  * ·如果没有,自己创建一个新事务,方法必须运行在事务中 
  * ·(存在事务就加入事务/或创建事务 成为一个整体,失败回滚也同一起儿Rollback-Only-)  
  * · 整体一起提交、一起回滚
  * 
  * Requires_new(vt. 需要New)	
  * ·每次创建一个新事务,如果当前已经在事务中了,会挂起(Suspend)当前事务.
  * · 场景是: 该方法是个事务方法,方法内调用了另外一个事务方法==简称==外内(内外)双事务/嵌套多事务
  * · 被嵌套的事务称:内层_事务、 调用其它事务的方法体称:外层_事务
  * · -内层事务执行结束后、提交,与外事务无关联.
  * · -内层事务异常回滚,外层事务如没有try-catch处理异常,两者一同回滚,如处理过,外层不会回滚.
  * · -如没有两个以上的事务,默认被动使用默认 Required.
  * · -内层事务的传播机制为:Requires_new(vt. 需要New)	
  * 
  * Nested(adj. 嵌套的,内装的)
  * · 如果当前有事务,则嵌套在已存在的事务中作为一个其子事务(嵌套事务)
  * · 嵌套事务是独立回滚的,外层不受影响
  * · 但如果主事务提交,则会携带子事务一起提交,一起回滚
  * · 子事务异常,则父事务可以回滚或不回滚
  * · -内层事务的传播机制为:Nested(adj. 嵌套的,内装的)	
  * 
  * Mandatory(adj. 强制的)
  * · 该事务是强制性必须存在一个事务/独占,如果没有,则抛出异常.
  * · 调用必须用事务,外层没有事务抛出异常
  * · 同外事务一起提交、一起回滚.
  *
  * Ont_Supported(adj. 不支持的)
  * · 事务存在就挂起,方法体执行完毕后,事务恢复进行(外层事务)
  * · 方法体与事务无关,执行完就会提交,不受外层事务是否结束后再提交
  * · 内层事务:Ont_Supported(adj./不支持的)
  * 
  * Supports(v. 支持)	
  * · 当前有事务就使用事务,当前没有则无状态/不使用事务.
  * · 单个方法调用时Supports事务传播机制行为,Never行为状态 一样.
  * · 外层事务有事务,它就有事务,其它无状态
  * 
  * Never(adv. 从未)
  * · 当前有事务存在,则抛出异常
  * · 不支持事务
  * · 不能被事务操作,但有事务方法调用就抛出异常
  */

/*默认-事务隔离级别 */
Isolation isolation() default Isolation.DEFAULT;
/** 默认 Default(v. 不履行)
  * · 标识使用数据库默认的事务隔离级别 
  * · MySql 默认隔离级别:-Repeatable_Read(可重复读)
  * · Oracle 默认隔离级别:-Read_Committed(读已提交)
~剩下 四个事务隔离级别与JDBC的隔离级别相对应~.
  *  -Read_Uncommitted(读未提交) 脏读、不可重复读、幻读问题
  * ·允许其它事务看到,当前事务未提交的数据.
  * 
  * -Read_Committed(读已提交) 不可重复读、幻读问题
  * · 保证一个事务修改数据已提交后,才能被另外一个事务读取.
  * 
  * 不可重复读 就是一个事务读到另一个事务修改后并提交的数据(update)。
  *  可重复读  就是不允许其它事务操作/独占策略 (行锁机制:不能更新/删除数据)
  * -Repeatable_Read(可重复读) 幻读问题
  * -Serializable(串行化) (表锁机制)
  */

/*默认-事务超时 */
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/** 默认None(没有)超时时间[-1]、事务超时自动回滚-Rollback
  * 疑问开始之前,先说四个不同层de超时相关的设置:
  * 1-Spring@TransactionTimeOut(超时) 
  * · 目的是为了一个事务执行时间超过某个预知时间后抛出异常.
  * · 一个事务中包含多个Statement(声明)对象
  * · 但一个Statement(声明)的执行时间流程:		
  * 包括(MybatisTimeOutJdbcTimeOutMysql中的innodb_Lock_Wait_TimeOut(超时))
  * ·以及建立Connection连接的持续时间,及连接MysqlWait_TimeOut(超时问题).
  * 2-1-MybatisTimeOut(超时)
  * · 目的是为了在某个Statement(声明)时间太久时被中止.
  * 2-2-JDBC——Connection连接池的Wait_TimeOut(间隔超时)
  * · 目的持续Connection 连接执行最近一个Statement(声明)
  * 到当前Statement(声明)的时间间隔
  * ·JDBCConetionTimeoutSocketTimeout不设置,MysqlServer端突然中断,客户端一直阻SocketInputStream.Read();
  * ·DruidDataSourceConnectionTimeoutSocketTimeout两个属性来实现.
  * ·jdbc:mysql://xxx.xx.xxx.xxx:3306/database?connectTimeout=60000&socketTimeout=60000.
  * 			4-Mysqlinnodb_Lock_Wait_TimeOut(超时)
  * 				· 目的是针对两个事务,同时更新同一行记录时,等待的最长时间.
  * 				· 该变量...Wait_TimeOut..,事务等待行锁的时间。默认是50s.
  * 				· Mysql指令查看超时变量: show variables like '%timeout%'
  * 				· innodb_Rollback_On_TimeOut变量,事务等待超时之后,进行回滚的策略。默认是OFF(关闭)* 				· 表示只回滚到上一个Statement,每执行一个SQL语句(一个Satement)就有一个保存点,
  * 				· 此时是回滚到上一个保存点。如果这个值改为ON(打开),那此时事务就进行整体回滚,即执行了Rollback* 					MysqlWait_TimeOut(超时问题).
  * 				· 通过 show processlit 指令可以 查看连接Connection线程Thread连接Sleep(睡眠)时间数值
  * 				· 这个时间数值是这个Connection执行最近一个Statement到当前的时间间隔。
  * 				  这个时间就是设置开一个客户端,不做任何操作的时候的连接保持时间。
  * 
  *     总结一下:
  * 		(1) Spring_@Transaction_TimeOutMybatis_TimeOutJDBC级别的TimeOut(超时)并没有更改Mysql的属性超时,
  * 		# 归纳一下前三者的实现:
  * 		一· 对于Spring@Transactional是通过TimeOut属性初始化了一个Deadline(最终期限)* 					每一次创建Statment判断Deadline是否小于0,如果小于0抛异常;
  * 					否则通过JDBCStatement#setQueryTimeout()来设置超时.
  * 		二·  MybatisTimeOut也是通过通过JDBCStatement#setQueryTimeOut来设置超时。
  * 		三·  JDBCTimeOut是在Statement执行时,开启了一个监听线程发现超时就终端当前执行的Statement,然后抛异常。
  * 		  # 最重要一点儿,只有MySQL层没有超时的情况下。上层的JDBC或者Spring层的TimeOut才有意义。
  * 
  * 			
  * 
  * 说下Mysql中的核心处理一节:
  * 		Statement接口对象(java.sql.Statement)QueryTimeout(查询超时)处理过程;
  * 		· 通过调用Connection接口的CreateStatement()方法创建Statement对象接口(该对象用于执行静态SQL语句的对象),
  * 		· 调用StatementExecuteQuery()方法,返回ResultSet对象接口(该对象代表数据库结果集的数据表),
  * 		· Statement接口对象的setQueryTimeOut()方法,设置超时时间, 
  * 		· Statement通过自身ConnectionQuery发送给MySQL数据库,
  * 		· Statement创建一个新的TimeOut-Execution线程用于超时处理,
  * 		· 每次、每个Connection接口对象都会分配一个TimeOut-Execution线程,
  * 		· 然后向TimeOut-Execution线程进行注册,达到超时时间
  * 		· TimerThread调用JTDS-Statement实例中的TsdCore.cancel()取消方法
  * 		· Timeout-Execution线程创建一个和Statement配置相同的Connection,
  * 		· 使用新创建的Connection向超时Query发送Cancel取消 QueryKill QueryConnectionId”)
  * 
  */
}

Guess you like

Origin blog.csdn.net/Rinvay_Cui/article/details/114408496