- 事务(Transaction)是为解决数据安全操作提出的,事务控制实际上就是控制数据的安全访问。
(银行转账业务,将A账户资金减少和B账户资金增加放到同一个事务里,要么全部执行成功,要么全部撤销,这样就保证了数据的安全性。)
- 事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。
- 事务是不可分割的的操作集合(工作逻辑单元)
———————————————————————————————————————————————————————————————————
事务必须服从ISO/IEC所制定的ACID原则。即事务四大特性
- 原子性(atomicity)
事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。
- 一致性(consistency)
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果事务被迫中断没有及时撤销先前执行过的所有指令,导致写入数据库一部分数据,此时就处于不一致状态,没有保证数据的完整性。
- 隔离性(isolation)
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)
指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的,即使此时再执行回滚操作也不能撤消所做的更改。
———————————————————————————————————————————————————————————————————
事务属性的种类: 传播行为、隔离级别、只读、事务超时
- 传播行为
( 传播行为定义了被调用方法的事务边界 )
传播行为 propagation | 意义 |
PROPAGATION_REQUIRED | 方法必须运行在一个事务内,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务。 |
REQUIRES_NEW | 创建一个新的事务,如果存在当前事务的话,暂停(挂起)当前事务 。 |
SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
NOT_SUPPORTED | 不执行当前事务;总是执行非事务。 |
MANDATORY | 支持当前事务;如果当前事务不存在则抛出一个异常。 |
NESTED | 如果当前存在事务的话,执行一个嵌套的事务,不存在创建新的。 |
NEVER | 不支持当前事务;如果存在当前事务则抛出一个异常 |
- 隔离级别
在操作数据时可能带来 3 个副作用,分别是脏读、不可重复读、幻读。在标准的 SQL 语句中定义了 4种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在 spring 事务中提供了 5 种隔离级别。
隔离级别 | 意义 |
ISOLATION_DEFAULT | 数据库默认的隔离级别。 |
_READ_UNCOMMITTED | 允许读取未提交的数据(对应未提交读),可能导致脏读、不可重复读、幻读。 |
_READ_COMMITTED | 允许在一个事务中读取另一个已经提交的事务中的数据(对应已提交读)。可以避免脏读,但是无法避免不可重复读和幻读。 |
_REPEATABLE_READ | 一个事务不可能更新由另一个事务修改但尚未提交(回滚)的数据(对应可重复读)。可以避免脏读和不可重复读,但无法避免幻读。 |
_SERIALIZABLE | 这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行(对应可序列化)。可以避免脏读、不可重复读、幻读。但是这种隔离级别效率很低,因此,除非必须,否则不建议使用。 |
- 只读
如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式( READ_ONLY_MARKER ) , 这样更有利于数据库进行优化 。
因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为(PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事务标记成只读才有意义。
如果使用 Hibernate 作为持久化机制,那么将事务标记为只读后,会将 Hibernate 的 flush 模式设置为 FULSH_NEVER, 以告诉 Hibernate 避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。
- 事务超时
如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设
置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。
———————————————————————————————————————————————————————————————————
- 脏读:脏读表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录A,此时该事务还未提交,然后另一个事务尝试读取记录A,这时其是会成功读取到记录A的;
- 不可重复读:不可重复读表示当前事务对同一记录的两次重复读取结果不一致。比如一个事务首先读取一条记录A,读完之后另一个事务将该记录修改并且成功提交了,然后当前事务再次读取记录A,此时该事务会发现两次读取的结果不一致;
- 幻读:幻读指的是一个事务在进行一次查询之后发现某个记录不存在,然后会根据这个结果进行下一步操作,此时如果另一个事务成功插入了该记录,那么对于第一个事务而言,其进行下一步操作(比如插入该记录)的时候很可能会报错。从事务使用的角度来看,在检查一条记录不存在之后,其进行插入应该完全没问题的,但是这里却抛出主键冲突的异常。