事务概念一组数据库操作要么全部成功要么全部失败回滚四大特性ACIDA原子性Atomicity即不可分割C一致性ConsistencyI隔离性IsolationD持久性Durability一致性一致性不是指数据不变而是事务执行前后数据完整性不变即业务规则不能被破坏隔离性多个事务修改同一数据万一冲突怎么办锁机制行锁一个事务修改某行其他事务阻塞等待MVCC 多版本InnoDB 保存旧版本快照读的时候读快照不加锁快照读。持久性本来不就是写入MySQL了持久性有什么好说的你以为 “修改成功写入数据库” 就是写到磁盘了其实不是。 操作系统有页缓存 SQL 执行完数据库先把数据写到内存缓冲区还没刷到硬盘。 如果此时数据库进程宕机、服务器断电内存数据直接消失。 持久性就是靠数据库的redo log事务提交前先把变更日志写入磁盘redo log 落盘。就算内存里的数据没刷到数据文件宕机重启后数据库读取 redo log 恢复数据。提交成功 redo 日志持久到磁盘不是一定把数据页刷盘。这就是持久性。Spring事务两大实现方式1.声明式事务Transactional注解可加在类/方法上加类类中所有 public 方法都继承该事务配置加方法仅该方法生效方法优先级 类级别⚠️ 注解只对 public 方法生效private/protected 默认不触发 AOP 代理。2.编程式事务示例Service public class UserService { Autowired private TransactionTemplate transactionTemplate; public void addUser(){ transactionTemplate.execute(status - { //数据库操作 userMapper.insert(...); //抛异常自动回滚 return true; }); } }事务传播机制即A 方法有事务调用 B 方法也带 TransactionalB 用哪种事务即子方法遇到已有事务时怎么选择事务传播类型含义REQUIRED默认有事务就加入当前事务没有就新建事务。最常用REQUIRES_NEW新建独立事务挂起外层事务内外事务互不影响。外层回滚不影响内层提交SUPPORTS有事务就加入无事务就非事务执行MANDATORY必须在已有事务内执行外层无事务直接抛异常NOT_SUPPORTED不使用事务如果外层有事务先挂起外层事务执行NEVER绝对不能在事务内执行外层存在事务直接抛异常NESTED嵌套事务基于保存点 savepoint内层异常回滚到保存点不会回滚外层。外层回滚内层一起回滚。区别于 REQUIRES_NEW不是独立事务有事务就加入当前事务什么意思场景A 方法带事务A 调用 B 方法B 也是Transactional(REQUIRED)。A 已经开启事务了 → B 不会新建事务直接共用 A 同一个事务共用同一个数据库连接。事务隔离级别区分事务四大特性为了解决并发事务问题脏读、不可重复读、幻读隔离级别脏读不可重复读幻读READ_UNCOMMITTED 读未提交✅存在✅存在✅存在READ_COMMITTED 读已提交 (Oracle 默认)❌✅存在✅存在REPEATABLE_READ 可重复读 (MySQL 默认)❌❌✅存在InnoDB 靠 MVCC 解决大部分幻读SERIALIZABLE 串行化❌❌❌Spring 事务 和 MySQL 事务 的关系 区别Spring 事务是上层封装MySQL 事务是底层实现。Spring 事务本质就是调用 MySQL 原生事务 API。 没有 MySQL数据库的事务能力Spring 事务完全无法生效。spring 只是帮你自动写setAutoCommit(false)、commit、rollback。MySQL 事务Spring 事务所属层级数据库层面Java 应用框架层面能力提供 ACID、锁、MVCC、redo/undo log真正实现提交回滚管理事务生命周期传播行为AOP 自动控制事务边界隔离级别真正生效数据库实现脏读、幻读控制Spring 只是把隔离级别参数传给数据库本身不实现隔离传播行为❌数据库没有传播机制✅Spring 特有数据库完全没有事务传播REQUIRED/REQUIRES_NEW/NESTED 这些传播规则是 Spring 在应用层实现Spring事务底层原理(AOPThreadLocal)1.容器启动扫描带Transactional的类生成动态代理对象2.调用事务方法时进入代理拦截器 TransactionInterceptor【代理前置逻辑】 → 执行业务方法 → 【代理后置逻辑】3.获取事务资源ThreadLocal绑定链接4.执行业务代码mapper此时不会自动提交因为当前线程绑定的连接 autocommitfalse所有 SQL 都在同一个事务里5.目标方法执行正常结束执行 commit 提交事务抛出异常执行 rollback 回滚6.释放资源清除ThreadLocal绑定核心事务资源绑定在线程上同一个线程内多个方法共用同一个数据库连接事务失效核心根源Spring 事务靠 AOP 动态代理拦截方法。只要没有走代理对象执行目标方法事务直接失效。 事务失效 TransactionInterceptor没有执行不会执行开启 / 提交 / 回滚逻辑。事务的超时、只读 特性超时Transactional(timeout 10)单位秒含义事务允许的最长执行时间超过时间就强制回滚。⚠️注意这个超时判断是 Spring 层面不是 MySQL 的 wait_timeout。只读告诉数据库这个事务只做查询不做增删改。这是一个提示不是强制拦截。有必要吗不加注解的话两条 SQL 是两个独立事务中间别的事务提交修改第二次查询会读到新数据。 加了 readOnly 事务两次查询在同一个事务快照保证可重复读。
阅读完成 · 觉得有帮助?