Spring事务原理

首先得知道程序是如何连接数据库的?

DataSource封装了Connection,Connection封装了Socket,程序最终是使用这个Socket来连接数据库的,对数据库的一些命令(execute、commit、rollback、close)都是通过Socket发送到数据库执行。而TransactionManager管理execute、commit、rollback、close方法。

数据库的事务原理

1、事务的概念

事务(Transaction)是访问或更新数据库中数据的一个程序执行单元(unit)。
特点:事务是恢复和并发控制的基本单位,具有四个特性(ACID):

  • 原子性(Automicity):一个事务是一个不可分割的工作单位,一个事务中的操作要么都做,要么都不做。
  • 一致性(Consistency):事务必须是使数据库从一个一致性状态变为另一个一致性状态。一致性和原子性密切相关。
  • 隔离性(Isolation):一个事务的执行不能被其他事务干扰。即一个事务的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  • 持久性(Durability):一个事务一旦提交,它对数据库中数据的改变就是永久性的。接下来的其他操作或故障不应该对其有任何影响。

2、事务的基本流程

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring是无法提供事务功能的。纯JDBC操作数据库事务的步骤:
1、获取连接:Connection conn = DriverManager.getConnection();
2、开启事务:conn.setAutoCommit(true/false);
3、执行CRUD
4、提交事务/回滚事务,conn.commit()/conn.rollback();
5、关闭连接:conn.close();
Spring的事务管理可以帮我们完成2和4,在使用@Transactional注解后,Spring会在有这个注解的地方开启事务的正常提交、异常回滚。
不配置事务的话,conn.setAutoCommit(true/false)默认为true,没有交给Spring来托管。而在交给Spring管理后,conn.setAutoCommit(true/false)则会被设置为false

事务执行的流程:

<img src=""https://dddz97.oss-cn-hangzhou.aliyuncs.com/img/20200910194857.png"" style=""zoom: 40%;"" />

通过流程来看代码:

DataSourceTransactionManager中,有doCommit()方法和doRollback()方法:

可以看到,两者都是调用了con的commit()和rollback()方法:

首先判断autoCommit是否为true,如果是true,就会抛出createSQLException异常。最后执行的是execSQL,即将""commit""这句sql提交到数据库执行。

可以看到rollback也是一样:

从代码中可以看到,commit、rollback操作,都是通过向数据库传输“commit”的sql语句“rollback”的sql语句来进行的。所以真正的事务操作实际是在数据库里进行的(通过数据库的binlog或者redo log实现)。

3、事务在数据库中的过程

粗略的描述一下:


4、Spring事务的传播属性

Spring事务的传播属性,就是定义在多个事务同时存在的时候,Spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义。

propagation 说明
PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务,则新建一个事务执行。这是Spring默认的事务传播属性。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务。外部事务失败回滚之后,不能回滚内部事务执行的结果。内部事务失败抛出异常,被外部事务捕获,也可以不处理回滚操作。
PROPAGATION_SUPPORTS 支持当前事务,如果没有当前事务,则以非事务的方式执行
PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,则抛出异常
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
PROPAGATION_NEVER 以非事务方式执行操作,如果当前存在事务,则抛出异常
PROPAGATION_NESTED 如果有活动事务,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器有效

5、事务隔离级别

5.1 数据库中的事务隔离级别

隔离级别                                           导致的问题
Read-Uncommitted(读未提交) 0 导致脏读
Read-Committed(读已提交) 1 避免脏读,允许不可重复读和幻读
Repeatable-Read(可重复读) 2 避免脏读、不可重复读,允许幻读
Serializable(串行化) 3 串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读,执行速度慢。
  • 脏读:一个事务对数据进行了增、删、改,但未提交,另一个事务可以读取到未提交的数据。此时如果第一个事务回滚,那么第二个事务就读到了脏数据。
  • 不可重复读:一个事务中发生了两次读操作,在第一次读和第二次读操作之间,另外一个事务对数据进行了修改,这时两次读取的数据是不一致的。
  • 幻读:第一个事务对一定范围的数据进行了批量修改,第二个事务在这个范围内增加了一条数据,此时第一个事务就会丢失对新增数据的修改。

大部分数据库(SQLServer、Oracle、pgSQL)的事务隔离级别是Read-Committed(读已提交),少部分(MySQL、InnoDB)是Repeatable-Read(可重复读)

5.2 Spring中的事务隔离级别

常量 解释
ISOLATION_DEFAULT 这是PlatformTransactionManager默认的事务隔离级别,使用的是数据库默认的事务隔离级别。另外4个与JDBC的事务隔离级别相对应。
ISOLATION_READ_UNCOMMITTED 这是最低的事务隔离级别,它允许另外一个事务看到这个事务未提交的数据。会产生脏读、不可重复读、幻读。
ISOLATION_READ_COMMITTED 保证一个事务修改的数据在commit之后才能被另一个事务读取。
ISOLATION_REPEATABLE_READ 防止脏读、不可重复读,但是可能出现幻读。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。
文章已创建 17

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部