1. Spring 的事务传播行为实现原理

%%
▶2.🏡⭐️◼️【🌈费曼无敌🌈⭐️第一步⭐️】◼️⭐️-point-20230413-1415%%
❕ ^27ji6t

Spring 的事务信息是存在 ThreadLocal 中的,所以一个线程永远只能有一个事务
%%
2217-🏡⭐️◼️Spring 事务的实现原理◼️⭐️-point-20230214-2217%%

  1. **融入 (NESTED)**:当传播行为是融入外部事务则拿到 ThreadLocal 中的 Connection、共享一个数据库连接共同提交、回滚; 
  2. **创建新事务 (REQUIRES_NEW)**:当传播行为是创建新事务,会将嵌套新事务存入 ThreadLocal、再将外部事务暂存起来;当嵌套事务提交、回滚后,会将暂存的事务信息恢复到 ThreadLocal 中

1.1. 融入

try {
3. 内嵌: 判断 ThreadLocal 是否已经有 Connection, 有的话就说明是一个内嵌事务, 判断当前事务的传播行为
如果是融入: ==不会创建 Connection, 返回事务状态信息==(TransactionInfo.newTransaction=false)
1、外部: 创建一个数据库连接 Connection 存入 ThreadLocal, 并且修改数据库连接的 autoCommit 属性为 false 返回事务状态信息 (TransactionInfo.newTransaction=true)
2、外部: 然后执行目标方法方法 (调用了内部事务方法) 方法中会执行数据库操作 sql
4. 内嵌: 然后执行目标方法方法方法中会执行数据库操作 sql
}
catch{
如果出现了异常, 并且这个异常是需要回滚的就会回滚事务, 否则仍然提交事务
}
5. 内嵌: 判断 newTransaction=true 就将要提交事务,但因为融入 (TransactionInfo.newTransaction=false) 所以暂时不会提交事务
6、外部: 判断 newTransaction=true 拿到 ThreadLocal 中的 Connection 进行提交

1.2. 创建新事务

try {
3. 内嵌: 判断 ThreadLocal 是否已经有 Connection, 有的话就说明是一个内嵌事务, 判断当前事务的传播行为
创建新事务:
① 把外层事务相关的事务信息(Connection、隔离级别、是否只读…. ) 暂存同时会把外层事务的 ThreadLocal 存储的事务信息都置空
② 创建自己的 Connection 放入 ThreadLocal,返回事务状态信息 (TransactionInfo.newTransaction=ture,TransactionInfo. 外部事务的信息暂存)
1、外部. 创建一个数据库连接 Connection 存入 ThreadLocal, 并且修改数据库连接的 autoCommit 属性为 false 返回事务状态信息 (TransactionInfo.newTransaction=true)
2、外部. 然后执行目标方法方法 (调用了内部事务方法) 方法中会执行数据库操作 sql
4. 内嵌: 然后执行目标方法方法方法中会执行数据库操作 sql
}
catch{
如果出现了异常, 并且这个异常是需要回滚的就会回滚事务, 否则仍然提交事务
}
5. 内嵌: 判断 newTransaction=true 就提交事务,因为融入 (TransactionInfo.newTransaction=true) 所以会提交事务,然后把暂存的事务信息回归 ThreadLocal 中
6、外部: 判断 newTransaction=true 拿到 ThreadLocal 中的 Connection 进行提交

2. 源码分析

https://www.51cto.com/article/621225.html
https://wiyi.org/how-does-transaction-suspension-in-spring.html
https://blog.csdn.net/wwh578867817/article/details/51736723
https://segmentfault.com/a/1190000013341344
http://www.skjava.com/article/1396186471

3. 实战经验

4. 参考与感谢

1、Spring-基础