数据库事务的隔离级别
数据库事务的隔离级别
问题:上述问题理论上如果出现了应该如何解决?
答:一般情况,数据库都会处理一些事务并发的问题,数据库提供了不同的事务隔离级别来处理不同的事务并发问题,事务隔离级别定义如下:
隔离级别 | 说明 |
---|---|
READ_UNCOMMITED (read_uncommited) | 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读(相当于没有做任何事务隔离) |
READ_COMMITTED (read_committed) | 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生(ORACLE默认级别) |
REPEATABLE_READ (repeatable_read) | 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。(MYSQL默认级别) |
SERIALIZABLE (serlalizable) | 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。(ORACLE支持) |
针对不同隔离级别可以解决的的如下五类问题
解决丢失更新的方案
数据库表数据加锁
1,悲观锁
(1) 在操作当前数据的事务开启事务就使用for update 锁住当前数据
(2) Hibernate和MyBatis都有悲观锁对应的解决方案
2,乐观锁
(1) 为表添加一个version字段。当前事务操作的时候都会比对当前事务情况的多次操作的版本号是否一致,如果不一致认为数据已经被更新
(2) Hibernate和MyBatis都有乐观锁对应的解决方案
Spring对事务的支持
- 为什么需要使用Spring是事务
答:使用Spring是事务代理(事务管理器),已经将事务的具体代码封装好,只需要在spring配置文件中配置一次,不用重复编写事务处理代码!!
Spring框架针对事务处理提供专门的解决方案
Spring的事务管理主要包括3个接口
Spring事务处理接口 | 描述 |
---|---|
TransactionDefinition | 封装事务的隔离级别超时时间,是否为只读事务和事务的隔离级别和传播规则等事务属性,可通过XML配置具体信息 |
PlatformTransactionManager | 根据TransactionDefinition提供的事务属性配置信息,创建事务。事物管理器 |
TransactionStatus | 封装了事务的具体运行状态。比如,是否是新开启事务,是否已经提交事务,设置当前事务为rollback-only等 |
TransactionDefinition
该接口主要定义了:事务的传播行为(规则),事务的隔离级别,获得事务信息的方法。所以在配置事务的传播行为,事务的隔离级别已经需要获得事务信息时,可以通过查阅该类的代码获得相关信息。
TransactionDefinition源码
public interface TransactionDefinition {
//事务的传播行为(规则)
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
//事务的隔离级别
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
//事务超时管理
int TIMEOUT_DEFAULT = -1;
//获得事务信息
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}
事务传播规则
Spring在TransactionDefinition接口中定义了七种事务传播规则,规定了事务方法和事务方法发生嵌套调用时事务该如何进行传播
事务传播规则类型 | 描述 |
---|---|
PROPAGATION_REQUIRED (propagation_required) | 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务(最常用操作)-Spring****默认使用的就是此规则 |
PROPAGATION_REQUIRES_NEW (propagation_requires_new) | 创建一个新的事务,如果当前存在事务,则把当前事务挂起 |
PROPAGATION_SUPPORTS (propagation_supports) | 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行 |
PROPAGATION_NOT_SUPPORTED (propagation_not_supported) | 以非事务方式运行,如果当前存在事务,则把当前事务挂起 |
PROPAGATION_NEVER (propagation_never) | 以非事务方式运行,如果当前存在事务,则抛出异常 |
PROPAGATION_MANDATORY (propagation_mandatory) | 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常 |
PROPAGATION_NESTED (propagation_nested) | 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED |
PlatformTransactionManager事务管理器
PlatformTransactionManager接口主要定义事务的处理方法,获取事务,开启事务,提交事务,回滚事务,在实际开发中不同的框架有不同的实现类
Spring的事务管理:
-
PlatformTransactionManager:接口统一抽象处理事务操作相关的方法;
1):TransactionStatus getTransaction(TransactionDefinition definition):
根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务,并用TransactionStatus描述该事务的状态。
2):void commit(TransactionStatus status):
根据事务的状态提交事务,如果事务状态已经标识为rollback-only,该方法执行回滚事务的操作。
3):void rollback(TransactionStatus status):
将事务回滚,当commit方法抛出异常时,rollback会被隐式调用 -
在使用spring管理事务的时候,首先得告诉spring使用哪一个事务管理器,使用不同的框架(JdbcTemplate,MyBatis,Hibernate/JPA )使用事务管理器都不同
PlatformTransactionManager事物管理器的继承体系图
3. 常用的事务管理器:
DataSourceTransactionManager:使用JDBC,MyBatis的事务管理器;