数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。事务具有的优点是:把逻辑相关的操作分成了一个组;在数据永久改变前,可以预览数据变化;能够保证数据的读一致性。
1.原子性(Atomicity):原子性是指一个事务中的操作,要么全部成功,要么全部失败,如果失败,就回滚到事务开始前的状态。
2.一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。那转账举栗子,A账户和B账户之间相互转账,无论如何操作,A、B账户的总金额都必须是不变的。
3.隔离性(Isolation):隔离性是当多个用户 并发的 访问数据库时,如果操作同一张表,数据库则为每一个用户都开启一个事务,且事务之间互不干扰,也就是说事务之间的并发是隔离的。再举个栗子,现有两个并发的事务T1和T2,T1要么在T2开始前执行,要么在T2结束后执行,如果T1先执行,那T2就在T1结束后在执行。关于数据的隔离性级别,将在后文讲到。
4.持久性(Durability):持久性就是指如果事务一旦被提交,数据库中数据的改变就是永久性的,即使断电或者宕机的情况下,也不会丢失提交的事务操作。
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
传播行为主要是影响事务的提交状态。
比如有两个事务,事务A和事务B,事务B的过程中调用了事务A,当事务A发生了异常,事务B如何处理事务,这个就是我们要定义的事务传播行为。
而在实际的处理过程中,事务A和事务B都是虚拟的,只是为最后事务处理结果提供一个记录,我们通过事务传播行为来影响最终的结果。
要了解隔离级别,我们应该先想清楚一下要解决的问题
Spring 隔离级别设置
事务管理方面我们会面临一些问题,比如:多事务管理,每个方法都需要写事务就很麻烦;组件使用方式不一致,不同的组件代码书写方式同,比如jdbc 和 hibernate,从而使得我们在切换组件时变得很困难。这时候我们就需要用到强大的spring事务管理了。spring事务管理提供了统一的事务编程模式以及编程式事务及声明式事务(AOP)。为我们解决数据库事务的管理问题。
public interface PlatformTransactionManager { //事务管理器通过TransactionDefinition,获得“事务状态”,从而管理事务 TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; //根据状态提交 void commit(TransactionStatus var1) throws TransactionException; //根据状态回滚 void rollback(TransactionStatus var1) throws TransactionException; }
有两个重要的事务管理器 DataSourceTransactionManager 和 HibernateTransactionManager
DataSourceTransactionManager 是以JDBC实现的
HibernateTransactionManager 是以Hibernate实现的
TransactionDefinition是用来定义事务的,其中的方法包括:
TransactionStatus是用来存储和修改事务状态的,其中的方法包括:
添加schema,需要在项目xml中添加aop 和 tx的schame
定义事务管理器,不同的连接用不同的事务管理器,如jdbc 和 hibernate
定义advice,来指定不同的事务性设置
定义pointcut,aop的切入点
@Transactional
事物传播行为介绍:
@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
事物超时设置:
@Transactional(timeout=30) //默认是30秒
事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化
MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED