首先呢? 事務的傳播行為是針對 ‘嵌套事務而言’ 疑問所在?
先說 Spring 傳播機制級別/型別、
~七種:事務傳播機制/行為 ~ ~五類:事務隔離級別
- 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的@Transaction的TimeOut(超時)
* · 目的是為了一個事務執行時間超過某個預知時間后拋出例外.
* · 一個事務中包含多個Statement(宣告)物件
* · 但一個Statement(宣告)的執行時間流程:
* 包括(Mybatis的TimeOut、Jdbc的TimeOut、Mysql中的innodb_Lock_Wait_TimeOut(超時))
* ·以及建立Connection連接的持續時間,及連接Mysql的Wait_TimeOut(超時問題).
* 2-1-Mybatis的TimeOut(超時)
* · 目的是為了在某個Statement(宣告)時間太久時被中止.
* 2-2-JDBC——Connection連接池的Wait_TimeOut(間隔超時)
* · 目的持續Connection 連接執行最近一個Statement(宣告)
* 到當前Statement(宣告)的時間間隔
* ·JDBC的ConetionTimeout和SocketTimeout不設定,MysqlServer端突然中斷,客戶端一直阻SocketInputStream.Read()上;
* ·DruidDataSource的ConnectionTimeout和SocketTimeout兩個屬性來實作.
* ·jdbc:mysql://xxx.xx.xxx.xxx:3306/database?connectTimeout=60000&socketTimeout=60000.
* 4-Mysql的innodb_Lock_Wait_TimeOut(超時)
* · 目的是針對兩個事務,同時更新同一行記錄時,等待的最長時間.
* · 該變數...Wait_TimeOut..,事務等待行鎖的時間,默認是50s.
* · Mysql指令查看超時變數: show variables like '%timeout%'
* · innodb_Rollback_On_TimeOut變數,事務等待超時之后,進行回滾的策略,默認是OFF(關閉),
* · 表示只回滾到上一個Statement,每執行一個SQL陳述句(一個Satement)就有一個保存點,
* · 此時是回滾到上一個保存點,如果這個值改為ON(打開),那此時事務就進行整體回滾,即執行了Rollback,
* Mysql的Wait_TimeOut(超時問題).
* · 通過 show processlit 指令可以 查看連接Connection執行緒Thread連接Sleep(睡眠)時間數值
* · 這個時間數值是這個Connection執行最近一個Statement到當前的時間間隔,
* 這個時間就是設定開一個客戶端,不做任何操作的時候的連接保持時間,
*
* 總結一下:
* (1) Spring_@Transaction_TimeOut、Mybatis_TimeOut、JDBC級別的TimeOut(超時)并沒有更改Mysql的屬性超時,
* # 歸納一下前三者的實作:
* 一· 對于Spring的@Transactional是通過TimeOut屬性初始化了一個Deadline(最終期限),
* 每一次創建Statment判斷Deadline是否小于0,如果小于0拋例外;
* 否則通過JDBC的Statement#setQueryTimeout()來設定超時.
* 二· Mybatis的TimeOut也是通過通過JDBC的Statement#setQueryTimeOut來設定超時,
* 三· JDBC的TimeOut是在Statement執行時,開啟了一個監聽執行緒發現超時就終端當前執行的Statement,然后拋例外,
* # 最重要一點兒,只有MySQL層沒有超時的情況下,上層的JDBC或者Spring層的TimeOut才有意義,
*
*
*
* 說下Mysql中的核心處理一節:
* Statement介面物件(java.sql.Statement)的QueryTimeout(查詢超時)處理程序;
* · 通過呼叫Connection介面的CreateStatement()方法創建Statement物件介面(該物件用于執行靜態SQL陳述句的物件),
* · 呼叫Statement的ExecuteQuery()方法,回傳ResultSet物件介面(該物件代表資料庫結果集的資料表),
* · Statement介面物件的setQueryTimeOut()方法,設定超時時間,
* · Statement通過自身Connection將Query發送給MySQL資料庫,
* · Statement創建一個新的TimeOut-Execution執行緒用于超時處理,
* · 每次、每個Connection介面物件都會分配一個TimeOut-Execution執行緒,
* · 然后向TimeOut-Execution執行緒進行注冊,達到超時時間
* · TimerThread呼叫JTDS-Statement實體中的TsdCore.cancel()取消方法
* · Timeout-Execution執行緒創建一個和Statement配置相同的Connection,
* · 使用新創建的Connection向超時Query發送Cancel取消 Query(Kill Query “ConnectionId”)
*
*/
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/267110.html
標籤:其他
上一篇:MySQL資料優化的方式總結
