---
title: "JDBC的事务和隔离级别"
source: https://www.boris1993.com/jdbc-transaction-and-isolation-level.html
date: 2019-02-27
updated: 2026-10-10
tags: [Java, JDBC, Transaction, Isolation level]
categories: [学知识]
---

# JDBC的事务和隔离级别

这里简单写一下我对`JDBC`的事务和隔离级别的理解。

# 名词解释

## 事务

数据库事务是DBMS执行过程中的一个逻辑单位，由一个有限的数据库操作序列构成。  
一个事务一定是具有`原子性(atomic)`、`一致性(consistency)`、`隔离性(isolation)`、`持久性(durability)`，即`ACID`。  
一个事务会包含一个或多个`数据操作语句(data-manipulation statements)`和查询语句。  
通常来说，事务会依照如下的流程执行：

1.  开始一个事务
    
2.  执行一系列操作或查询语句
    
3.  如果没有发生错误，则提交这个事务，并将其结束
    
4.  如果发生了错误，则回滚这个事务，并将其结束。
    

## ACID

-   Atomic

原子性，即一个事务内的所有操作都被作为一个整体看待，要么全部成功，要么全部失败

-   Consistency

一致性，即事务中有操作失败时，这个事务所更改的数据都必须回滚至操作前的状态。

-   Isolation

隔离性，即事务所查看到的数据，要么是一个事务提交前的状态，要么是一个事务提交后的状态，而不可能是事务在执行中的状态。

-   Durability

持久性，即事务对系统的影响是永久的。

## 读现象

-   脏读

当一个事务允许读取另一个事务修改但尚未提交的数据时，就有可能发生脏读。

-   不可重复读

在一次事务中，对一行数据的两次读取获得了不同的结果。  
该现象发生于在执行`SELECT`时没有获得读锁，或者在读取完毕后立刻释放了读锁。

-   幻读

在事务执行过程中，两个完全一样的查询得到了不同的结果集，即是幻读。它是不可重复读的一个特殊场景。  
当事务1在执行两次`SELECT ... WHERE`操作中间，事务2在这个表中生成了一行新数据，而这条新数据正好满足事务1的`WHERE`条件，导致事务1的两次查询得到了不同的结果集。

# 隔离级别

## `NONE`

`NONE`是一个特殊的级别，代表`JDBC`驱动不支持事务。

## 未提交读(`READ UNCOMMITED`)

这个是最低的隔离级别。  
这个隔离级别允许事务读取到其他事务尚未提交(commit)的数据，即允许脏读。

## 提交读(`READ COMMITED`)

这个隔离级别中，DBMS需要选定对象的写锁一直保持到事务结束，但是读锁会在`SELECT`操作完成后马上释放，所以有可能会发生“不可重复读”。

## 可重复读(`REPEATABLE READ`)

在这个隔离级别下，DBMS需要对选定对象的读锁和写锁一直保持到事务结束，但是不要求范围锁，所以有可能发生幻读。

## 可串行化(`SERIALIZABLE`)

这是最高的隔离级别。  
在这个隔离级别下，要求DBMS在选定对象上的读锁和写锁一直保持到事务结束，如果使用了`WHERE`来描述范围时，则应当获取一个范围锁。这个隔离级别可以防止幻读。

# 隔离级别与读现象

| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| :-- | :-- | :-- | :-- |
| 未提交读 | 可能发生 | 可能发生 | 可能发生 |
| 提交读 | 不会发生 | 可能发生 | 可能发生 |
| 可重复读 | 不会发生 | 不会发生 | 可能发生 |
| 可串行化 | 不会发生 | 不会发生 | 不会发生 |

# 隔离级别与锁持续时间

| 隔离级别 | 写操作 | 读操作 | 范围操作 |
| :-- | :-- | :-- | :-- |
| 未提交读 | 当前语句执行完毕 | 当前语句执行完毕 | 当前语句执行完毕 |
| 提交读 | 当前事务提交 | 当前语句执行完毕 | 当前语句执行完毕 |
| 可重复读 | 当前事务提交 | 当前事务提交 | 当前语句执行完毕 |
| 可串行化 | 当前事务提交 | 当前事务提交 | 当前事务提交 |
