事务
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
- 事务用来管理 insert,update,delete 语句
事务必须满足的4个条件(ACID)
- 原子性(atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样
- 一致性(consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作
- 隔离性(isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致
- 持久性(durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
并发事务所导致的问题
- 脏读:对于两个事务t1和t2,t1读取了已经被t2更新但还没有被提交的字段。之后,若t2回滚,则t1读取的内容就是临时且无效的
- 不可重复读:对于两个事务t1和t2,t1读取了一个字段,然后t2更新了该字段。之后,t1再次读取同一个字段,值就发生变化了
- 幻读:对于两个事务t1和t2,t1从一个表中读取了几行数据,然后t2在该表中插入了一些新的行。之后,如果t1再次读取该表时就会多出几行
spring支持的事务隔离级别
隔离级别 | 描述 |
---|
DEFAULT | 使用底层数据库的默认隔离级别,对于大多数数据库来说,默认隔离级别为READ_COMMITTED |
READ_UNCOMMITTED(读未提交) | 允许事务读取未被其它事务提交的变更。脏读、不可重复读和幻读的问题都会出现 |
READ_COMMITTED(读已提交) | 只允许事务读取已经被其它事务提交的变更。可以避免脏读,但不可重复读和幻读问题仍然可能出现 |
REPEATABLE_READ(可重复读) | 确保事务可以多次从一个字段中读取相同的值。在这个事务持续期间,禁止其它事务对这个字段进行更新,可以避免脏读和不可重复读,但幻读的问题仍然存在 |
SERIALIZABLE(串行化) | 确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其它事务对该表执行插入,更新和删除操作。所有并发问题都可以避免,但性能十分低下 |
事务的传播属性
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行
spring支持的事务传播行为
传播属性 | 描述 |
---|
REQUIRED | 如果有事务在运行,当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行 |
REQUIRED_NEW | 当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,则将它挂起 |
SUPPORTS | 如果有事务正在运行,当前的方法就在这个事务内运行,否则可以不运行在事务中 |
NOT_SUPPORTED | 当前方法不运行在事务中,如果有运行的事务,将它挂起 |
MANDATORY | 当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常 |
NEVER | 当前的方法不应该运行在事务中。如果有运行的事务,就抛出异常 |
NESTED | 如果有事务正在运行,当前的方法就应该在这个事务的嵌套事务内运行。否则,就启动一个新的事务,并在它自己的事务内运行 |
@Transactional注解
- spring允许简单地使用@Transactional注解来标注事务
- 根据spring AOP 基于代理机制,只能标注公有方法
- 可以在方法或者类上添加该注解