spring之事务管理

来源:互联网 发布:c语言大小写转换代码 编辑:程序博客网 时间:2024/04/29 18:59

事务简介:

事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性

事务就是一系列的动作,它们被当作一个单独的工作单元。这些动作要么全部完成,要么全部不起作用

事务的四个关键属性(ACID)

① 原子性(atomicity):事务室一个原子操作,有一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用
② 一致性(consistency):一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中
③ 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏
④ 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中

Spring中的事务管理

作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层。而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制。

Spring既支持编程式事务管理,也支持声明式的事务管理

编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码

声明式事务管理:大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。

Spring事务的传播属性:

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

事务的传播行为可以由传播属性指定。Spring定义了7种传播行为:

Spring支持的事务传播行为传播行为含义PROPAGATION_MANDATORY表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常PROPAGATION_NESTED表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务PROPAGATION_NEVER表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常PROPAGATION_NOT_SUPPORTED表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManagerPROPAGATION_REQUIRED表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务PROPAGATION_REQUIRED_NEW表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManagerPROPAGATION_SUPPORTS表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行

其中PROPAGATION_REQUIRED为默认的传播属性

并发事务所导致的问题

在同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。

并发事务所导致的问题可以分为以下三类:

① 脏读:脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。

② 不可重复读:不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间更新了数据

③ 幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录


并发事务所导致的问题解决方案之事务隔离

解决并发问题的途径是什么?答案是:采取有效的隔离机制。怎样实现事务的隔离呢?隔离机制的实现必须使用锁,下面是锁的基本原理:

 

a.当一个事务访问某个数据库资源时,如果执行的是select语句,必须为资源加上共享锁,如果执行的是insert,update,delete语句,必须为资源加上排他锁,这些锁锁定正在被操作的资源。

b.当第二个事务也要反问相同的资源时,如果执行的select语句,那么也必须为资源加上共享锁;如果执行的是insert,update,或delete语句,也必须为资源加上排他锁。但此时第二个事务并非就立即能为资源加上锁,当第一个事务为资源加的是共享锁时,第二个事务能够为资源加上共享锁,但当第一个事务为资源加的是排他锁时,第二个事务必须等待第一个事务结束,才能为资源加上排他锁。

 

上面已经引出了,共享锁,排他锁。下面来阐述一下锁的种类及概念。

 

1.共享锁

共享锁用于读取数据操作,它允许其他事务同时读取锁定的资源,但不允许其他事务更新它。

2.排他锁

排他锁用于修改数据的场合,他锁定的资源,其他事务部能读取也不能修改。

3.更新锁

更新锁在更新操作初始化截断用来锁定可能要被修改的资源,从而避免使用共享锁造成的死锁现象。

 

锁机制能有效地解决并发事务时的各种问题,但是也会影响到并发的性能。数据库系统提供了4种可选的事务隔离级别,它们是

a.Read Uncommited:读未提交的数据

b.Read commited:读已提交的数据

c.Repeateble Read:可重复读

d.Serialable:串行化

 

Read Uncommited: 该隔离级别读取数据时不使用任何锁。可能会出现脏读,不可重复读,和虚读的问题。

 

Read commited:返回的是读取时间点之前已提交的数据,因此可以避免脏读。但重复读数据时,返回的数据和读取时间点有关,因此会重现不可重复读,另外还会出现虚读现象。

 

Repeatable Read:该隔离级别能够保证重复读,可以避免脏读和不可重复读问题。

 

 

 

 

Serializable:该隔离级别能够避免脏读,不可重复读和虚读现象,是最严格的隔离级别。

 

上面四种隔离级别,从a-d隔离级别越来越严格,数据安全和真实性越来越高,但并发性能越来越低。所以选择什么样的隔离级别应根据应用的具体要求而定。


0 0
原创粉丝点击