© 版权声明:本文为博主原创文章,转载请注明出处
1.什么是事务
- 事务是指逻辑上的一组操作,这组操作要么全部成功,要么全部失败
2.事务特性(ACID)
- 1.原子性(Atomicity):指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
- 2.一致性(Consistemcy):指事务前后数据的完整性必须保持一致
- 3.隔离性(Isolation):指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离
- 4.持久性(Durability):指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响
3.Spring事务API
Spring事务管理高层抽象主要包括3个接口
- PlatformTransactionManager:事务管理器
Spring为不同的持久化框架提供了不同的PlatformTransactionManager接口实现
1)使用Spring JDBC或者iBatis进行数据持久化时使用DataSourceTransactionManager
2)使用Hibernate进行数据持久化时使用HibernateTransactionManager
3)使用JPA进行数据持久化时使用JpaTransactionManager
4)使用Jdo进行数据持久化时使用JdoTransactionManager
5)使用JTA进行数据持久化,在一个事务跨越多个资源时必须使用JtaTransactionManager
- TransactionDefinition:事务定义信息(隔离、传播、超时、只读)
不考虑隔离性可能出现的问题
1)脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据回滚,则读到的数据是无效的
eg:事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的
2)不可重复读:是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据
eg:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果
3)幻读:一个事务读取了几行记录后,另一个事务插入一些数据,幻读就发生了。在后来的查询中,第一个事务就会发现有些原本没有的记录
eg:事务T1对一个表中的全部数据进行了修改。同时,事务T2向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,
就好象发生了幻觉一样
注:不可重复和幻读的区别:
结果:
1)不可重复读的重点是修改:同样的条件, 你读取过的数据, 再次读取出来发现值不一样了
2)幻读的重点在于新增或者删除:同样的条件, 第1次和第2次读出来的记录数不一样
控制:
1)对于不可重复读, 只需要锁住满足条件的记录,就可避免
2)对于幻读, 要对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),才可避免
隔离级别
- DEFAULT:使用后端数据库默认的隔离级别
- READ_UNCOMMITTED:允许你读取还未提交的改变了的数据。可能导致脏读、幻读、不可重复读
- READ_COMMITTED:允许在并发事务已经提交后读取。可防止脏读,但幻读和不可重复读仍可发生
- REPEATABLE_READ:对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏读、不可重复读,但幻读仍可能发生
- SERIALIZABLE:完全服从ACID的隔离级别,确保不发生脏读、幻读、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的
注:MySQL默认采用REPEATABLE_READ ORACLE默认采用READ_COMMITTED
事务传播行为:解决业务层方法之间的相互调用的问题
- PROPAGATION_REQUIRED:支持当前事务,不存在就创建一个
- PROPAGATION_SUPPORTS:支持当前事务,不存在就不使用事务
- PROPAGATION_MANDATORY:支持当前事务,不存在就抛出异常
- PROPAGATION_REQUIRES_NEW:如果有事务存在,挂起当前事务,创建一个新的事务
- PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果有事务存在,挂起当前事务
- PROPAGATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
- PROPAGATION_NESTED:如果当前事务存在,则嵌套事务执行
4.Spring的两种事务管理
- 编程式事务管理
1)实际应用中比较少用
2)通过TransactionTemplate手动管理事务
- 声明式事务管理
1)推荐使用(代码侵入性最小)
2)Spring的声明式事务是通过AOP实现的