spring事务简单理解
事务基本概念
事务是访问并可能更新数据库中各种数据项的一个程序执行单元unit
事务的特点:原子性、一致性、隔离性、持久性;统称为ACID特性
原子性(Automciity)一个事务是不可分割的一部分,事务中包含的所有操作,要不都做,要么不做
一致性(Consistency),事务必须使数据从一个状态变成另一种状态,要么都成功,要么都失败,该属性和原子性密切相关
隔离性(Isolation),事务的执行,是不能被其他事务所干扰的,即该事务中的所有操作,仅针对该事务的可见,其他事务均不可见,并发是各个事务不能互相干扰
持久性(Durability),事务一经提交,它是数据库的改变是永久的,不可逆的;
事务的基本原理
spring事务的本质,还是的需要数据的支持。现有的也是在jdbc驱动上的,AOP的形式进行扩展
JDBC原生态操作数据的步骤如下:
1.获取连接
2.开始事务
3.执行CRUD
4.提交/回滚事务
5.关闭连接
使用spring管理后,我们代码中可以再也不用手工写步骤2和4了,spring会通过AOP自动给我们织入2和4,并达到事务的管理,spring 管理事务包含下面两种方式:
1.注解式事务
配置文件开始注解驱动,在相关类和方法上通过注解@Transactional标识
Spring在启动时会加载相关注解,并生成bean,在生成bean的时候,会扫描拥有该注解的方法,如果拥有该注解,则会为该类生成代理类,并根据@Transactional后面值,进行配置注入
这样就在代理中把相关事务处理掉,真正的底层事务提交和回滚是通过binlog和redolog来实现的
2.声明式事务
该事务通过XML配置,具体配置如下
定义数据源
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
配置事务通知属性
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
<tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
<tx:method name="trannew*" propagation="REQUIRES_NEW" rollback-for="Exception,RuntimeException,SQLException"/>
<tx:method name="login" propagation="NOT_SUPPORTED"/>
<tx:method name="query*" read-only="true"/>
</tx:attributes>
</tx:advice>
配置事务的具体类
<aop:config>
<aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"/>
<aop:aspect ref="dataSource">
<aop:pointcut id="transactionPointcut" expression="execution(public * com.jlg..*.service..*Service.*(..))" />
</aop:aspect>
</aop:config>
注:优先级是注解式事务>声明式事务
事务的传播属性
常量 | 含义 |
REQUIRED | 支持当前事务,如果当前没有事务,就新建一个事务,也是spring中的默认事务 |
REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务 挂起。新建的事务将和被挂起的事务没有任 何关系,是两个独立的事务,外层事务失败 回滚之后,不能回滚内层事务执行的结果, 内层事务失败抛出异常,外层事务捕获,也 可以不处理回滚操作 |
SUPPORTS | 支持当前事务,如果当前没有事务,则以非事务方式执行 |
MANDATORY | 支持当前事务,如果当前没有事务则抛出异常 |
NOT_SUPPORTED | 以非事务的方式执行,如果当前存在事务则挂起 |
NEVER | 以非事务方式执行,如果当前存在事务则抛出异常 |
NESTED | 嵌套事务,如果一个活动的事务存在,则运行在一个嵌套事务中,如果没有活动事务则按照REQUIRED属性执行。它使用了一个单独的事务,该事务可以拥有多个回滚点,内部事务回滚不会对外部事务造成影响,它只对DataSourceTransactionManager 事务管 理器起效 |
数据库中的隔离级别
隔离级别 | 导致的问题 |
0. Read-Uncommitted | 导致脏读 |
1.Read-Committed | 避免脏读,允许不可重复读和幻读 |
2.Repeatable-Read | 避免脏读,不可重复读,允许幻读 |
3.Serializable | 串行化,事务只能一个个执行,避免脏读,重复读,幻读,执行效率慢,需慎重 |
脏读一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如 果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一 个事务对数据进行了修改,这时候两次读取的数据是不一致的。
幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数 据,这时候第一个事务就会丢失对新增数据的修改。
影响:
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。 大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle 少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB
spring中的数据库隔离级别
常量 | 解释 |
ISOLATION_DEFAULT | 这是个 PlatfromTransactionManager 默 认的隔离级别,使用数据库默认的事务隔离 级别。另外四个与 JDBC 的隔离级别相对 应。 |
ISOLATION_READ_UNCOMMITTED | 这是事务最低的隔离级别,它允许另外一个 事务可以看到这个事务未提交的数据。这种 隔离级别会产生脏读,不可重复读和幻像 读。 |
ISOLATION_READ_COMMITTED | 保证一个事务修改的数据提交后才能被另 外一个事务读取。另外一个事务不能读取该 事务未提交的数据。 |
ISOLATION_REPEATABLE_READ | 这种事务隔离级别可以防止脏读,不可重复 读。但是可能出现幻像读。 |
ISOLATION_SERIALIZABLE | 这是花费最高代价但是最可靠的事务隔离 级别。事务被处理为顺序执行。 |
分布式事务
微服务盛行,分布式事务是个很棘手的问题,所以它抛弃了事务的强一致性,慢慢的为了容错和可用性转变为最终一致性,也是CAP原理
分布式系统的特点
在分布式系统中,同时满足 CAP 定律中的一致性 Consistency、可用性 Availability 和 分区容错性 Partition Tolerance 三者是不可能的。在绝大多数的场景,都需要牺牲强一 致性来换取系统的高可用性,系统往往只需要保证最终一致性。 分布式事务服务(Distributed Transaction Service,DTS)是一个分布式事务框架,用 来保障在大规模分布式环境下事务的最终一致性。 CAP 理论告诉我们在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络 硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的,所以我们只 能在一致性和可用性之间进行权衡。 为了保障系统的可用性,互联网系统大多将强一致性需求转换成最终一致性的需求,并 通过系统执行幂等性的保证,保证数据的最终一致性。
数据一致性理解:
强一致性:当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更 新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。 根据 CAP 理论,这种实现需要牺牲可用性。
弱一致性:系统并不保证后续进程或者线程的访问都会返回最新的更新过的值。系统在 数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可 以读到。
最终一致性:弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回 上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟, 系统负载和复制副本的个数影响。DNS 是一个典型的最终一致性系统。