A 事务定义:
事务是指多个操作单元组成的合集,这些单元操作是不可分割的整体,所有操作要么都不成功,要么都成功
B 四个属性(ACID):
原子性 atomicity: 即事务是不可分割的最小工作单元,事务内的操作要么全做,要么全不做
一致性 consistency: 在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是应该处于正确的状态,即数据完整性约束没有被破坏如银行转帐,A转帐给B,必须保证A的钱一定转给B,一定不会出现A的钱转了但B没收到,否则数据库的数据就处于不一致 不正确 的状态
隔离性 isolation: 并发事务执行之间互不影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性
持久性 durability: 事务一旦执行成功,它对数据库的数据的改变必须是永久的,不会因比如遇到系统故障或断电造成数据不一致或丢失
一致性 consistency: 在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是应该处于正确的状态,即数据完整性约束没有被破坏如银行转帐,A转帐给B,必须保证A的钱一定转给B,一定不会出现A的钱转了但B没收到,否则数据库的数据就处于不一致 不正确 的状态
隔离性 isolation: 并发事务执行之间互不影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性
持久性 durability: 事务一旦执行成功,它对数据库的数据的改变必须是永久的,不会因比如遇到系统故障或断电造成数据不一致或丢失
C 事务的类型:
1 本地事务和分布式事务
1> 本地事务:普通事务,只涉及一个数据源,保证在该数据库上操作的ACID
2> 分布式事务:涉及两个或多个数据源的事务,由跨越多台同类或异类的多个数据源的事务共同组成,分布式事务旨在保证这些本地事务的所有操作的ACID
1> 本地事务:普通事务,只涉及一个数据源,保证在该数据库上操作的ACID
2> 分布式事务:涉及两个或多个数据源的事务,由跨越多台同类或异类的多个数据源的事务共同组成,分布式事务旨在保证这些本地事务的所有操作的ACID
2 Java中事务类型分为JDBC事务和JTA事务
3 按是否通过编程实现事物控制
分为声明式事务:通过XML配置或者注解实现, 无侵入,不影响业务逻辑的实现
编程式事:通过代码在业务逻辑中需要管理事务时自行实现,粒度更小,侵入式
D Spring事务隔离级别
ISOLATION_DEFAULT : 用底层数据库的默认隔离级别ISOLATION_READ_UNCOMMITTED(未提交读): 最低隔离级别,事务还未提交,就可被其他事务读取(会出现幻读,脏读,不可重复读)
ISOLATION_READ_COMMITTED(提交读): 事务提交后才能被其他事务读取(禁止其他事务读取到未提交事务的数据,会幻读,不可重复读),sql server默认级别
ISOLATION_REPEATABLE_READ(可重复读): 保证多次读取同一个数据时,读到的值都和事务开始时的内容一致,禁止读到其他未提交事务的数据(基本可防止脏读,不可重复读,会出现幻读)(MySql默认级别,更改可通过set transaction isolation level 级别)
ISOLATION_SERIALIZABLE(序列化): 代价最高但最是可靠(能防止脏读,不可重复读,幻读)
E Spring事务传播行为
PROPAGATION_REQUIRED: 支持当前事务,如当前没有事务,新建一个
PROPAGATION_SUPPORTS: 支持当前事务,如当前没有事务,以非事务执行
PROPAGATION_SUPPORTS: 支持当前事务,如当前没有事务,以非事务执行
PROPAGATION_MANDATORY: 支持当前事务,如当前没有事务,抛出异常(强制一定要在一个已经存在的事务中执行,业务方法不可独自发起自己的事务)
PROPAGATION_REQUIRES_NEW: 始终新建一个事务,如已经存在事务,则把原事务挂起
PROPAGATION_NOT_SUPPORTED: 不支持当前事务,始终以非事务方式执行,如当前事务存在,挂起该事务
PROPAGATION_NEVER: 不支持当前事务 如果当前事务存在,则引发异常
PROPAGATION_NESTED: 如果当前事务存在,则在嵌套事务中执行,如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作(注意: 当应用到JDBC时,只适用JDBC 3.0以上驱动)
PROPAGATION_NOT_SUPPORTED: 不支持当前事务,始终以非事务方式执行,如当前事务存在,挂起该事务
PROPAGATION_NEVER: 不支持当前事务 如果当前事务存在,则引发异常
PROPAGATION_NESTED: 如果当前事务存在,则在嵌套事务中执行,如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作(注意: 当应用到JDBC时,只适用JDBC 3.0以上驱动)
F Spring事务支持
Spring支持事务管理的核心是事务管理器抽象,对不同的数据访问框架通过实现策略接口PlatformTransactionManager,从而支持多种数据访问框架的事务管理
1 事务管理器, spring提供了多种内置事务管理器以支持不同数据源,常见的事务管理器有:
1> org.springframework.jdbc.datasource.DataSourceTransactionManager: 对javax.sql.DataSource类型的数据源提供事务支持,适用于JDBC,Mybatis等框架事务管理
1> org.springframework.jdbc.datasource.DataSourceTransactionManager: 对javax.sql.DataSource类型的数据源提供事务支持,适用于JDBC,Mybatis等框架事务管理
2> HibernateTransactionManager: 对org.hibernate.SessionFactory类型的数据源提供事务支持,适用于集成Hibernate框架时的事务管理
3> org.springframework.transaction.jta.JtaTransactionManager: 对分布式事务管理的支持,将事务管理委托给JavaEE应用服务器,或自定义本地JTA事务管理器,嵌套到应用程序中实现事务管理
以上内置事务管理器都继承了
AbstractPlatformTransactionManager
, AbstractPlatformTransactionManager实现了
PlatformTransactionManager
接口
2 Spring分布式事务配置
G Spring编程式事务
PlatformTransactionManager,TransactionTemplate
H Spring声明式事务
1 <tx:advice>+<aop:config>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="remove*" propagation="REQUIRED"/> <tx:method name="edit*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="get*" read-only="true"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pointcut" expression="(execution(* com.dr.service.*.*(..)) or execution(* com.system.service.*.*(..)))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/> </aop:config>
2 @Transactional + <tx:annotation-driven transaction-manager="" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional注意点 如果在接口、实现类或方法上都指定了@Transactional,则优先级为: 方法 > 实现类 > 接口 建议只在实现类或实现类的方法上使用@Transactional,不要直接在接口上使用 因为,如果使用JDK代理机制(基于接口的代理)没有问题;但如果使用CGLIB代理(继承)机制时会遇到问题,原因是CGLIB代理使用基于类的代理而不是接口,此时接口上的@Transactional注解“不能被继承”
I ACID相关概念
丢失更新: 多个事务同时更新一行数据,后一个事务的更新会覆盖掉前面事务的更新,从而导致前面事务更新的数据丢失,这是由于没有加锁造成的
幻读: 同样的事务操作过程中,不同时间段多次(不同事务)读取同一数据,读取到的内容不一致(一般是行数变多或变少)
脏读: 一个事务读取到另外一个未提及事务的内容
不可重复读: 同一事务中,多次读取内容不一致(一般行数不变,而内容变了)
幻读与不可重复读的区别: 幻读测重于插入与删除,第二次查询比第一次查询数据变少或变多了; 而不可重复读侧重于修改,第二次的查询结果和一次查询结果不一致,即第一次的结果已经不可重现了
数据库隔离级别越高,执行代价越高,并发执行能力越差,因此在实际项目开发使用时要综合考虑,为了考虑并发性能一般使用提交读隔离级别,它能避免丢失更新和脏读,尽管不可重复读和幻读不能避免,但可以在可能出现的场合使用悲观锁或乐观锁来解决这些问题