# 隔离级别

URL: https://caijiao.org/postgresql/performance/transactions/isolation
Source: docs/postgresql/performance/transactions/isolation.md
Description: 本章节深入探讨 PostgreSQL 中的事务隔离级别，解释各级别的特性、适用场景以及可能导致的问题。

数据库事务的隔离性指的是一个事务的执行是否会被其他并发事务所影响。PostgreSQL 提供了四种标准的事务隔离级别，它们分别为：读未提交、读已提交、可重复读和串行化。不同的隔离级别提供不同的并发控制方式，从而影响事务的执行顺序、性能和一致性。

## 隔离级别的标准

根据 SQL 标准，数据库系统提供了四种隔离级别，分别是：

- **读未提交（Read Uncommitted）**
- **读已提交（Read Committed）**
- **可重复读（Repeatable Read）**
- **串行化（Serializable）**

每个隔离级别的主要区别在于它们允许一个事务在执行过程中看到其他事务所做的更改（也就是脏读、不可重复读和幻读）。

## 各级别说明

### 1. 读未提交（Read Uncommitted）

读未提交是最低的事务隔离级别，允许一个事务读取其他事务未提交的更改（脏数据）。这意味着即使其他事务还未提交，当前事务仍然可以读取到这些修改，可能会导致数据不一致或错误。

#### 特点：
- **脏读**：事务可以读取到其他事务未提交的数据。
- **不可重复读**：在同一事务中，查询的同一数据可能会被其他事务修改。

#### 适用场景：
通常不推荐使用此级别，因为它允许读取未提交的脏数据，可能导致不一致或错误的结果。

#### 示例：

```sql
-- 设置事务隔离级别为 READ UNCOMMITTED
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- 执行操作
COMMIT;
````

### 2. 读已提交（Read Committed）

读已提交是 PostgreSQL 的默认隔离级别。在此级别下，事务只会看到已提交事务的更改。换句话说，如果一个事务正在执行，而另一个事务对数据进行了修改并提交，那么第一个事务将不会看到这些未提交的数据。该级别避免了脏读问题。

#### 特点：

* **不可重复读**：事务中的同一查询，可能因为其他事务提交而得到不同的结果。
* **避免脏读**：事务只能看到已提交的数据。

#### 适用场景：

适用于大多数常见的数据库操作，提供了较高的并发性，且避免了脏读问题，但可能会遇到不可重复读。

#### 示例：

```sql
-- 设置事务隔离级别为 READ COMMITTED
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
-- 执行操作
COMMIT;
```

### 3. 可重复读（Repeatable Read）

在可重复读级别下，事务中的查询总是返回相同的数据值，即使其他事务在此过程中对数据进行了修改。这样保证了事务的一致性，避免了不可重复读的问题。但是，它仍然可能遇到幻读的问题，即查询的结果集可能会因其他事务的插入、删除等操作发生变化。

#### 特点：

* **避免脏读**：事务不会读取到其他未提交的数据。
* **避免不可重复读**：同一个查询在同一事务中返回的结果不会发生变化。
* **可能发生幻读**：事务中同一个查询的结果集可能因为其他事务的插入、删除等操作而发生变化。

#### 适用场景：

适用于需要保证在一个事务中查询的一致性，避免读取到不一致的数据，但要注意幻读问题。

#### 示例：

```sql
-- 设置事务隔离级别为 REPEATABLE READ
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
-- 执行操作
COMMIT;
```

### 4. 串行化（Serializable）

串行化是最高的事务隔离级别，提供最强的隔离性。在此级别下，事务会像顺序执行一样执行，即使多个事务并发运行，数据库也会确保它们的结果与按顺序执行一样。它通过序列化事务的执行顺序来避免所有并发冲突，包括脏读、不可重复读和幻读。

#### 特点：

* **避免脏读、不可重复读和幻读**：事务完全隔离，不受其他事务影响。
* **性能低**：为了保证最高的隔离性，可能会牺牲事务的并发性，导致性能下降。

#### 适用场景：

适用于需要确保事务执行完全一致性和完整性的场景，但需要注意会降低并发性能。

#### 示例：

```sql
-- 设置事务隔离级别为 SERIALIZABLE
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
-- 执行操作
COMMIT;
```

## 隔离级别的选择

选择合适的事务隔离级别需要根据应用的需求权衡数据一致性和性能。以下是一些建议：

* **低隔离级别（如读未提交）**：适用于不太关注一致性的高并发场景，如日志记录、缓存更新等，但一般不推荐用于实际数据操作。
* **默认隔离级别（读已提交）**：适用于大多数应用场景，能有效防止脏读，但可能出现不可重复读。
* **可重复读**：适用于需要保证同一事务中数据一致性的场景，但可能会遇到幻读问题。
* **串行化**：适用于需要完全数据一致性的应用场景，通常用于财务或银行等高度敏感的事务处理，但会导致性能瓶颈。

## 小结

PostgreSQL 提供的四种隔离级别为事务提供了不同程度的隔离性和一致性。根据具体的业务需求，开发者可以选择合适的隔离级别，以平衡数据一致性和性能的需求。合理选择隔离级别，有助于确保数据的一致性和事务的高效执行。
