---
title: "事务隔离级别概述 - OceanBase 数据库 V4.5.0 | OceanBase 文档中心"
description: 事务隔离级别概述 概述 隔离级别用于描述事务并发执行时互相干扰的程度。ANSI/ISO SQL 标准（SQL 92）基于事务执行过程中必须避免的异常情况定义了四种隔离级别，隔离级别越高，事务间的相互影响越小，允许出现的异常情况越少；在最高的隔离级别可串行化（Serializable）中，不允许出现任何异常情况。 其中…
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.5.0

# 事务隔离级别概述

更新时间：2025-12-27 09:20:28

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.5.0/zh-CN/700.reference/100.oceanbase-database-concepts/800.transaction-management/200.transaction-concurrency-and-consistency/400.transaction-isolation-level/100.transaction-isolation-level-overview.md)  

## 概述

隔离级别用于描述事务并发执行时互相干扰的程度。ANSI/ISO SQL 标准（SQL 92）基于事务执行过程中必须避免的异常情况定义了四种隔离级别，隔离级别越高，事务间的相互影响越小，允许出现的异常情况越少；在最高的隔离级别可串行化（Serializable）中，不允许出现任何异常情况。 其中这些需要避免的异常情况包括：

- 脏读（Dirty Read）：一个事务读到其他事务尚未提交的数据。
 - 不可重复读（Non Repeatable Read）：曾经读到的某行数据，再次查询发现该行数据已经被修改或者删除。例如：`select c2 from test where c1=1;` 第一次查询 `c2` 的结果为 `1`，再次查询由于其他事务修改了 `c2` 的值，因此 `c2` 的结果为 `2`。
 - 幻读（Phantom Read）：在执行请求中，当再次执行相同的搜索条件时，结果集中读取到了另一个已提交事务新插入的满足条件的行。

## 隔离级别种类

ANSI/ISO SQL 标准（SQL 92）定义了四种隔离级别，这四种隔离级别如下：

- 读未提交（Read Uncommitted）
 - 读已提交（Read Committed）
 - 可重复读（Repeatable Read）
 - 可串行化（Serializable）

四种隔离级别以及它们对上述异常情况的容忍程度如下所示：

| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| --- | --- | --- | --- |
| **读未提交** | 可能 | 可能 | 可能 |
| **读已提交** | 不可能 | 可能 | 可能 |
| **可重复读** | 不可能 | 不可能 | 可能 |
| **可串行化** | 不可能 | 不可能 | 不可能 |

## OceanBase 数据库隔离级别

OceanBase 数据库目前支持了以下几种隔离级别：

- Oracle 模式

     - 读已提交（Read Committed）
     - 可串行化（Serializable）
 - MySQL 模式

      该隔离级别类似 Oracle 数据库的 Serializable，并非严格意义上的 Serializable。

OceanBase 数据库默认的隔离级别为**读已提交（Read Committed）**。

实际在 OceanBase 数据库中只实现了两种隔离级别，即**读已提交**和**可串行化**，当用户指定**可重复读**的隔离级别时，实际使用的是**可串行化**；与此同时，当用户指定**读未提交**的隔离级别时，实际使用的是**读已提交**。也就是说，OceanBase 数据库的**可重复读**的隔离级别更加严格，不会出现幻读的异常情况。OceanBase 数据库的**读已提交**不会出现脏读的异常情况，可能会出现不可重复读和幻读的异常情况；而**可串行化**不会出现脏读、不可重复读以及幻读的异常情况。

### 读已提交

在 OceanBase 数据库的**读已提交**隔离级别下，每条 `SELECT` 语句执行时仅能够读到在此之前所有**已经提交事务**的数据，而不会读到在语句执行过程中新提交或被并发事务修改的数据，就像是在每条语句执行之前获取了当前数据库的最新快照。快照中只记录了已提交的数据，因此不会出现脏读的异象。但由于每条语句执行前会获取新的快照，在同一个事务中连续的两条 `SELECT` 语句有可能看到不同的数据，即**读已提交**隔离级别下不能避免不可重复读和幻读的异常情况。

对于 `UPDATE`、`DELETE`、`SELECT FOR UPDATE` 等更新操作，它们在搜索目标行时的行为与 `SELECT` 相同，即**只能找到在语句开始前已经提交的行版本**，如果该版本不满足更新操作的谓词条件，则直接跳过该行，如果满足条件，才尝试更新该行。然而，当前事务（简称事务 A）在尝试更新一个满足谓词条件的目标行时，该行可能已经被另一个并发事务（简称事务 B）更新。在这种情况下，若事务 B 还没有结束，事务 A 需要等待事务 B 的提交或回滚。如果事务 B 回滚，事务 A 可以继续更新目标行；如果事务 B 提交，**事务 A 将重新执行该语句**，从而重新获取语句快照，以读到事务 B 更新后的版本，如果该版本依旧满足谓词条件，则在此基础上再进行更新。

### 可重复读或可串行化

在 OceanBase 数据库的**可串行化**（或**可重复读**）隔离级别下，事务的**第一条语句**会获取当前数据库的快照作为**事务快照**，后续 `SELECT` 语句都会基于事务快照读取数据，只能读到在事务快照之前所有**已经提交事务**的数据，而不会读到在事务执行过程中新提交或被并发事务修改的数据。由于每条语句使用同一个事务快照，所以事务内总能看到一致的数据，不会出现不可重复读和幻读的异常情况。

对于 `UPDATE`、`DELETE`、`SELECT FOR UPDATE` 等更新操作，它们在搜索目标行时的行为与 `SELECT` 相同，即**只能找到在获取事务快照前已经提交的行版本**，如果该版本不满足更新操作的谓词条件，则直接跳过该行，如果满足条件，才尝试更新该行。然而，当前事务（简称事务 A）在搜索到一个目标行时，该行可能已经被另一个并发事务（简称事务 B）更新。在这种情况下，若事务 B 还没有结束，事务 A 需要等待事务 B 的提交或回滚。如果事务 B 回滚，事务 A 可以继续更新最初找到的行；如果事务 B 提交，事务 A 不能基于旧的快照进行更新，否则会出现丢失更新（Lost Update）的情况，因此**事务 A 只能进行回滚**，此时 OceanBase 数据库会返回下列错误信息：

- Oracle 模式：

  ```sql
  ORA-08177: can't serialize access for this transaction

  ```
 - MySQL 模式：

  ```sql
  ERROR 6235 (25000): can't serialize access for this transaction

  ```

业务层需要考虑到事务可能会因为写冲突而回滚，并准备事务重试逻辑。如果事务复杂，重试代价较大，且业务并不要求事务所有语句看到一致的数据情况，建议使用**读已提交**的隔离级别。

## OceanBase 数据库可串行化隔离级别的限制

在 SQL 标准中，**可串行化**隔离级别只需要避免脏读、不可重复读和幻读的异常情况，但是**可串行化**的严格定义为：任何两个成功提交的并发事务按顺序执行，一个事务在另一个事务之后，即事务的并行执行结果需要和某种串行执行的结果相同。与 Oracle、PostgreSQL 9.0 及之前的版本类似，OceanBase 数据库的**可串行化**隔离级别下并不能保证严格的可串行化，即事务执行的结果可能不与任何串行执行模式的结果相同。其中写偏斜（Write Skew）是一个经典例子： 假设存在表 `T1(num int)` 和 `T2(num int)`，两个表初始都没有数据。此时在事务 1（Trx1）和事务 2（Trx2）中按照以下顺序执行命令，

```sql
Trx1                                                  Trx2
BEGIN;
INSERT INTO T2 SELECT COUNT(*) FROM T1;

                                                      BEGIN;
                                                      INSERT INTO T1 SELECT COUNT(*) FROM T2;
COMMIT;
                                                      COMMIT:

```

由于 Trx1 和 Trx2 获取的快照中两个表的 `COUNT` 都为 0，最终表 T1 和表 T2 中都会插入 `num=0` 的一行，而假设事务 1 和事务 2 串行执行，无论是 `Trx1->Trx2` 还是 `Trx2->Trx1`，最终两个表应该会分别插入 `num=0` 和 `num=1`。OceanBase 数据库目前无法保证严格**可串行化**的原因在于其读操作不会上锁，读写不互斥，并且也没有在事务提交时检查读写冲突是否成环。在大部分现实应用场景下，只要不出现脏读、幻读和不可重复读就能够满足业务的需求，如果业务一定需要严格的**可串行化**，可以显式地为读操作加锁，如 `SELECT FOR UPDATE`。

#### 注意

串行化隔离级别下，开启事务后，会保留事务快照，事务提交后快照才会回收。因此，串行化隔离级别下，需要注意及时提交事务，否则可能遇到磁盘占用变大或者读取越来越慢的问题。

## OceanBase 数据库隔离级别与其他数据库对比

| 数据库 | 读未提交（Read Uncommitted） | 读已提交（Read Committed） | 可重复读（Repeatable Read） | 可串行化（Serializable） |
| --- | --- | --- | --- | --- |
| OceanBase | 仅支持语法 | 支持，与 SQL 标准一致 | 支持，且不存在幻读 | 支持，但不保证严格可串行化 |
| Oracle | 不支持语法 | 支持，与 SQL 标准一致 | 不支持语法 | 支持，但不保证严格可串行化 |
| MySQL | 支持，有可能读到脏数据 | 支持，与 SQL 标准一致 | 支持，且不存在幻读 | 支持，可以保证严格可串行化 |
| PostgreSQL 9.1 之前版本 | 支持语法，但实际是 Read Committed | 支持，与 SQL 标准一致 | 支持，且不存在幻读 | 支持，但不保证严格可串行化 |
| PostgreSQL 9.1 及之后版本 | 支持语法，但实际是 Read Committed | 支持，与 SQL 标准一致 | 支持，且不存在幻读 | 支持，可以保证严格可串行化 |

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
