02.JDBC的高级使用——事务提交模式和隔离级别

本文深入探讨JDBC中的事务管理机制,包括自动提交与手动提交模式的区别、事务的四大特性(ACID),以及如何通过设置不同的隔离级别来解决脏读、不可重复读和幻影读等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDBC的高级使用——事务提交模式和隔离级别

1. 事务提交模式

  • 自动提交模式

    默认方式,每执行完一条SQL语句就自动提交事务,每条SQL语句的执行都被单独提交,因此一个事务只有一条SQL语句组成。

  • 手动提交模式

    通常一个新的数据库连接产生,便意味着一个新的事务生成。我们要将一个整体操作设置为一个事务,而不是一条SQL语句当成一个事务。

    Conncetion.setAutoCommit(false):设置为手动提交模式

    Connection.commit():提交事务

    Connection.rollback():回滚事务

    一个事务中可以包含若干条SQL语句

2. 事务并发引发的问题

事务(Transaction),一般是指要做的或所做的事情。

事务是恢复和并发控制的基本单位。

事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。

  • 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

  • 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

  • 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

  • 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

并发引发的问题
  • 脏读(dirty read)

    一个事务读取另一个事务未提交的数据。

    例如,一个事务对数据库里面的数据进行读取,另一个事务对数据库进行更新,某一条数据记录原本为20,欲更新为100,在第二个事务提交之前,第一个事务读取到这个100,而此后第二个事务进行了回滚操作,这时,读取出来的数据即为脏数据。

  • 不可重复读(unrepeatable read)

    一个事务运行期间两次读取相同的数据但是内容不一致。原因可能是两次读取数据期间有另外一个事务对数据进行了修改。

  • 虚读/幻影读(phantom read)

    一个事务运行期间两次读取相同统计数据但内容不一致,原因是两次读取期间有其他事务执行了插入或删除符合统计条件的数据并提交。

3. 事务隔离级别

事务隔离(Transaction Isolation)

通过设置事务的隔离级别,来解决脏读、不可重复读、幻影读问题

五种事务隔离级别
  • TRANSACTION_NONE(0):不支持事务

  • TRANSACTION_READ_UNCOMMITTED(1):可读未提交数据

  • TRANSACTION_READ_COMMITTED(2):避免脏读

  • TRANSACTION_REPEATABLE_READ(4):避免不可重复读

  • TRANSACTION_SERIALIZABLE(8):避免幻影读

隔离级别dirty readunrepeatable readphantom read
read_uncommitted(1)yesyesyes
read_committed(2)noyesyes
repeatable read(4)nonoyes
serializable(8)nonono

1. 隔离级别越高,并发性能越差,一般将隔离级别设置为2

  1. Oracle的事务隔离级别:TRANSACTION_READ_COMMITTED(默认)和TRANSACTION_SERIALIZABLE

  2. MySQL的事务隔离级别:默认为4(TRANSACTION_REPEATABLE_READ),还可以为1,2,8

JDBC中获取事务隔离级别:Connection.getTransactionIsolation(),返回int值

JDBC中设置事务隔离级别:Connection.getTransactionIsolation(int level),参数可以为隔离级别数字代号,也可以是Connection的静态常量(如:Connection.TRANSACTION_REPEATABLE_READ)

### 事务回滚机制 当应用程序抛出异常时,Spring框架能够自动触发事务的回滚操作。默认情况下,运行时异常(RuntimeException及其子类)会导致事务被标记为回滚状态;而对于受检异常,则不会自动引发回滚除非显式配置[^1]。 对于自定义逻辑中的特定条件下的手动回滚需求,可以通过`setRollbackOnly()`方法来强制执行回滚动作。此外,在AOP环境下,如果希望某些类型的异常也能引起回滚,可以在`@Transactional`注解中指定这些异常类型作为rollbackFor参数值[^2]。 ```java @Transactional(rollbackFor = {CustomException.class}) public void methodThatShouldRollBackOnSpecificExceptions() { // Method implementation that may throw CustomException } ``` ### 事务隔离级别详解 SQL标准定义了几种不同的事务隔离级别以解决并发访问数据库资源时可能出现的一致性数据准确性问题: - **READ_UNCOMMITTED**: 允许读取尚未提交的数据变更,可能导致脏读、不可重复读幻象读现象。 - **READ_COMMITTED**: 只能读取已经提交的数据修改,防止了脏读的发生但仍然可能发生不可重复读幻象读。 - **REPEATABLE_READ**: 同一事务内多次查询返回相同的结果集,解决了不可重复读的问题,但在范围扫描场景下仍可能存在幻影读的情况。 - **SERIALIZABLE**: 提供最严格的隔离程度,完全杜绝了上述三种不一致性情况,代价是性能开销较大。 在Spring中设置隔离级别可通过`isolation`属性完成,该属性接受枚举形式的输入,如ISOLATION_DEFAULT表示采用底层JDBC驱动程序所支持的标准隔离等级[^3]。 ```java @Transactional(isolation = Isolation.SERIALIZABLE) public void highlyIsolatedOperation() { // Critical section requiring highest isolation level } ``` ### 事务传播行为 事务传播特性决定了多个事务性方法之间如何相互作用。以下是几种常见的传播策略: - **REQUIRED**:如果有现有事务则加入其中;如果没有就创建一个新的独立事务。这是最常见的选项,默认即为此项。 - **SUPPORTS**:若有现成事务便参与进去;否则以非事务方式继续执行。 - **MANDATORY**:必须在一个已有事务上下文中调用此方法,否则将抛出异常。 - **REQUIRES_NEW**:总是启动新事务,即使当前存在其他活动事务也会将其暂停并建立全新环境。 - **NOT_SUPPORTED**:建议不在任何事务范围内工作,如有必要会暂时挂起正在进行中的事务。 - **NEVER**:绝对不允许处于事务内部调用本函数,违反规定同样会造成错误响应。 - **NESTED**:类似于REQUIRED但是提供了更细粒度控制——它允许嵌套事务拥有自己单独的保存点以便局部失败不影响外部更大规模的操作。 通过调整`propagation`属性可以改变默认的行为模式,从而更好地适应具体应用场景的需求[^4]。 ```java @Transactional(propagation = Propagation.REQUIRED) public void typicalBusinessLogicMethod() { // Normal business logic here } @Transactional(propagation = Propagation.REQUIRES_NEW) public void criticalSectionNeedsNewTx() { // Logic needing its own transaction boundary } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值