事务可从多种层面进行分类,数据库角度、java角度、编程角度:
数据库角度
根据数据源的数量分为本地事务和全局事务
本地事务:普通事务,独立的一个数据库,保证在该数据库上操作的ACID。
分布式事务:涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),分布式事务旨在保证这些本地事务的所有操作的ACID,使事务可以跨越多台数据库;
java角度
根据规范分为JDBC事务和JTA事务
JDBC事务:普通事务,即数据库事务中的本地事务,通过connection对象控制管理。
JTA事务:JTA指Java事务API(Java Transaction API),是Java EE数据库事务规范, JTA只提供了事务管理接口,由应用程序服务器厂商(如WebSphere Application Server)提供实现,JTA事务比JDBC更强大,支持分布式事务(当然也支持本地事务)。
编程角度(Spring层面)
根据是否通过编程分为声明式事务和编程式事务
声明式事务:通过XML配置或者注解实现,更为简单
编程式事务:通过编程代码在业务逻辑时需要时自行实现,粒度更小。
详情可见:
备注: 声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
----------------------------------------------------------------------------------
接下来从Spring层面上,让我们总结一下事务的隔离级别和传播行为。
隔离级别
有5大隔离级别,这是在TransactionDefinition接口中定义的。
1、ISOLATION_DEFAULT:
用底层数据库的默认隔离级别,即数据库管理员设置成什么就是什么;
2、ISOLATION_READ_UNCOMMITTED(未提交可读):
最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)
3、ISOLATION_READ_COMMITTED(提交可读):
一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)、sql server的默认级别
4、ISOLATION_REPEATABLE_READ(可重复读):
可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(该隔离基本可防止脏读,不可重复读(重点在修改),但会出现幻读(重点在增加与删除))(MySql默认级别,更改可通过set
transaction isolation level 级别)
5、ISOLATION_SERIALIZABLE(序列化):
代价最高最可靠的隔离级别(该隔离级别能防止脏读、不可重复读、幻读)
默认为isolation_default(底层数据库默认级别),其他四个隔离级别跟数据库隔离级别一致。
备注:
幻读:同样的事务操作过程中,不同时间段多次(不同事务)读取同一数据,读取到的内容不一致(一般是行数变多或变少)。
不可重复读:同一事务中,多次读取内容不一致(一般行数不变,而内容变了)。
丢失更新:两个事务同时更新一行数据,最后一个事务的更新会覆盖掉第一个事务的更新,从而导致第一个事务更新的数据丢失,这是由于没有加锁造成的;
脏读:一个事务读取到另外一个未提及事务的内容,即为脏读。