Spring中的事务管理
【第一部分】
一、事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的完整性和一致性.
事务就是一系列的动作, 它们被当做一个单独的工作单元.这些动作要么全部完成,要么全部不起作用
二、事务的四个关键属性(ACID)
原子性(atomicity): 事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成要么完全不起作用.
一致性(consistency):一旦所有事务动作完成,事务就被提交.数据和资源就处于一种满足业务规则的一致性状态中.
隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏.
持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响.通常情况下,事务的结果被写到持久化存储器中.
三、用事务通知声明式地管理事务
示例代码
1.Spring.xml开头代码,配置文件的配置
2. 中间部分
3. 重要的配置
【第二部分】
1. 在 Spring 2.x事务通知中配置传播属性
在 Spring 2.x 事务通知中, 可以像下面这样在<tx:method>元素中设定传播事务属性
2. Spring 7种支持的事务传播行为
propagation="REQUIRED" 方法和方法之间父子关系
例子:<tx:method name="update*" propagation="REQUIRED" timeout="5"/>
REQUIRED [必须的]没有事务创建一个事务 有事务使用当前事务
EQUIRED_NEW 不管父方法是否存在事务 都会新建事务
SUPPORTS [支持]父方法存在事务 使用当前事务 没有事务 使用jdbc的事务(自动提交)
NOT_SUPPORTED 不管父方法是否存在事务 都不会使用事务(挂起事务)
MANDATORY [强制的]必须在事务环境下运行 父方法没有事务 抛出异常
No existing transaction found for transaction marked with propagation 'mandatory'
NEVER [决不]父方法不能存在 事务 有事务抛出异常
Existing transaction found for transaction marked with propagation 'never'
NESTED 有事务就在当前事务嵌套内运行 否则 启动新事务 运行
3. 事务的隔离级别
从理论上来说, 事务应该彼此完全隔离,以避免并发事务所导致的问题.然而,那样会对性能产生极大的影响,因为事务必须按顺序运行.
在实际开发中, 为了提升性能,事务会以较低的隔离级别运行.
事务的隔离级别可以通过隔离事务属性指定
4. Spring 支持的事务隔离级别
isolation="DEFAULT" 隔离级别
DEFAULT [默认]使用数据库本身的隔离级别ORACLE(读已提交) MYSQL(可重复读)
READ_UNCOMMITTED spring实现读未提交 (脏读)
READ_COMMITTED spring实现读已提交 (不可重复读+幻读)
REPEATABLE_READ spring实现可重复读 (幻读)
SERIALIZABLE spring实现串行化(已解决)
5. 事务的隔离级别要得到底层数据库引擎的支持,而不是应用程序或者框架的支持.
Oracle 支持的 2种事务隔离级别:READ_COMMITED , SERIALIZABLE
Mysql 支持 4中事务隔离级别.
6. 设置隔离事务属性
用 @Transactional 注解声明式地管理事务时可以在 @Transactional 的isolation属性中设置隔离级别.
在 Spring 2.x 事务通知中, 可以在<tx:method>元素中指定隔离级别
7. 设置回滚事务属性
在 Spring 2.x 事务通知中, 可以在<tx:method>元素中指定回滚规则.如果有不止一种异常,用逗号分隔.
总结:spring事务 运行过程中 碰到运行时异常 自动回滚 非运行时异常不会回滚
rollback-for="" 指定会自动回滚的非运行时异常
no-rollback-for="" 指定某些运行时异常抛出时 不回滚
8. 超时和只读属性
只读事务 (除特定的方法以外其他的业务逻辑方法都不应该操作事务)
read-only="true"设置只读事务
timeout=10-30左右 mysql默认10s自动超时 oracle永不超时
超时事务属性: 事务在强制回滚之前可以保持多久.这样可以防止长期运行的事务占用资源.
只读事务属性: 表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务.
设置超时和只读事务属性
9. 【重点】事务引发的问题和隔离级别
事务 对同一行数据进行操作时 必须等先操作的客户端提交或者回滚事务后另外一个客户端才能操作数据(锁)
事务操作同一行数据出现的问题 (并发的引发的问题)
脏读 不可重复读 幻读
脏读 【是一种错误】
读取到了用户未提交的数据 oracle数据库永远不会出现脏读
不可重复读 【只是一种设计问题】
在读取的事务中两次重复读取同一行数据发现数据被更改了
幻读【只是一种设计问题】
在读取的事务中两次读取某一个条件的多条数据时发现多出了几条数据
隔离级别 (就是为了解决事务操作同一份数据导致的问题)
READ UNCOMMITTED: 读未提交数据。脏读、不可重复读、幻读都可能发生。它的事务隔离性最低。
READ COMMITTED:读已提交数据。解决了脏读。【数据库的默认的隔离级别】
REPEATABLE READ:可重复读。解决不可重复读,脏读。
SERIALIZABLE:串行化。解决任何并发事务问题。最严格的事务
Oracle只支持READ COMMITTED和SERIALIZABLE。
默认为READ COMMITTED
【了解即可】
事务的提交方式 默认数据库使用手动(非自动)提交方式需要操作者使用commit关键字来提交
SQL> show autocommit;
autocommit OFF
10. 事务的四个特性【acid属性】
事务表示 一段sql的执行 要么同时成功 要么同时失败
原子性(Atomic):
指整个数据库事务是不可分割的工作单元。原子性确保在事务中的所有操作要么都发生,要么都不发生。
一致性(Consistency):
一旦一个事务结束了(不管成功与否),系统所处的状态和它的业务规则是一致的。即数据应当不会被破坏。
隔离性(Isolation):
指多个事务同时操作同一数据时,每个事务都有各自的完整数据空间。
未提交的数据 在其他的客户端中是无法看到因为因为隔离性
持久性(Durability):
一旦事务完成,事务的结果应该持久化
存到物理磁盘中(就是断电了下次还能看的到 )
11. 【问题】隔离级别怎样解决这些问题的
Sql多用户访问数据库其实就是事务并发,会引起如下问题:
脏读、不可重复读、幻读
处理以上隔离级别的问题,采用那些方式。