第三章 事务控制与并发机制

第一节 ACID 特性实现机制

目标:理解 PostgreSQL 中事务的基本概念及其对数据一致性的保障作用,掌握 ACID(原子性、一致性、隔离性、持久性)特性在 PostgreSQL 中的实现机制,并能够根据业务需求选择合适的事务隔离级别和并发控制策略。

事务是数据库系统中最基本也是最重要的抽象之一。它确保多个数据库操作要么全部成功,要么全部失败,从而保持数据的一致性和完整性。PostgreSQL 完全支持 ACID 事务,能够在高并发环境下提供可靠的数据处理能力。

本节将围绕以下核心内容展开:

  • 事务的基本概念与生命周期
  • ACID 四大特性的定义与实现方式
  • 多版本并发控制(MVCC)原理
  • 不同事务隔离级别的行为差异与适用场景

🧩 一、事务的基本概念与生命周期

1. 什么是事务?

事务是一组逻辑上相关的数据库操作,被视为一个不可分割的工作单元。例如:

1
2
3
4
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;

上述代码表示一次转账操作,两个更新要么都执行,要么都不执行。

2. 事务的生命周期

事务通常经历以下几个阶段:

阶段描述
BEGIN开始事务块
SQL 操作执行 DML 或 DDL 语句
COMMIT提交事务,永久保存更改
ROLLBACK回滚事务,撤销所有更改

⚠️ 如果未显式使用 BEGIN,PostgreSQL 默认每个语句都是一个自动提交事务。


🔐 二、ACID 特性详解

ACID 是衡量事务型数据库是否具备可靠数据处理能力的关键标准。PostgreSQL 在底层通过 WAL(Write-Ahead Logging)、MVCC 和锁机制来实现这四个关键特性。

1. 原子性(Atomicity)

含义:事务中的所有操作要么全部完成,要么全部不完成。

实现机制

  • 使用 WAL 记录事务日志
  • 若事务中途失败,通过回滚日志恢复到事务前状态

2. 一致性(Consistency)

含义:事务必须使数据库从一个一致性状态转换到另一个一致性状态。

实现机制

  • 约束检查(主键、外键、唯一约束)
  • 触发器和规则验证
  • 应用层逻辑一致性由开发人员保证

3. 隔离性(Isolation)

含义:多个事务并发执行时,彼此之间不能互相干扰。

实现机制

  • MVCC(多版本并发控制)
  • 行级锁、表级锁
  • 可配置的事务隔离级别

4. 持久性(Durability)

含义:一旦事务提交,其结果应永久存储在数据库中,即使发生系统崩溃也应能恢复。

实现机制

  • 写入 WAL 日志后才确认提交
  • 定期执行 Checkpoint 将内存页刷盘

🔄 三、多版本并发控制(MVCC)原理

MVCC 是 PostgreSQL 实现高并发事务处理的核心机制。它允许读写操作并行执行而无需加锁,从而避免了传统数据库中常见的“读写阻塞”问题。

1. 核心思想

  • 每一行数据都有多个版本(Version)
  • 事务只能看到在其开始时间点之前已提交的数据版本
  • 旧版本数据在事务不再需要后由 VACUUM 清理

2. 关键字段说明

PostgreSQL 表中的每条记录包含以下隐藏字段用于 MVCC:

字段含义
xmin插入该行的事务 ID
xmax删除或更新该行的事务 ID
cmin, cmax命令序号(用于同一事务内的多个操作)

3. 查询可见性判断流程

当事务查询某行数据时,PostgreSQL 会根据当前事务快照(Snapshot)判断该行是否对该事务可见。

示例说明:

  • 事务 A 插入了一行并提交 → 对后续事务可见
  • 事务 B 更新该行但未提交 → 其他事务看不到新版本
  • 事务 C 删除该行并提交 → 对后续事务不可见

4. MVCC 的优势

优势描述
高并发读操作不需要加锁
性能优越减少锁竞争,提高吞吐量
一致性视图每个事务看到一致的数据快照

🔐 四、事务隔离级别与行为差异

PostgreSQL 支持四种事务隔离级别,分别对应不同的并发行为和一致性要求。

隔离级别脏读不可重复读幻读丢失更新推荐使用场景
Read Uncommitted不推荐使用
Read Committed默认级别,适用于大多数 OLTP 场景
Repeatable Read避免幻读需使用锁或串行化
Serializable最高级别,适合金融类交易系统

设置事务隔离级别语法:

1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

也可以在会话级别设置:

1
2
3
SET LOCAL statement_timeout = '30s';
SET LOCAL lock_timeout = '5s';
SET LOCAL transaction_isolation = 'repeatable read';

🧪 五、实战演练:模拟并发事务冲突

场景描述:

两个用户同时尝试修改同一账户余额,观察不同隔离级别下的行为差异。

步骤 1:创建测试表

1
2
3
4
5
6
7
CREATE TABLE accounts (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    balance NUMERIC(10,2)
);

INSERT INTO accounts (name, balance) VALUES ('Alice', 1000);

步骤 2:用户 A 开始事务

1
2
3
4
-- 用户 A
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT balance FROM accounts WHERE name = 'Alice'; -- 输出 1000
UPDATE accounts SET balance = 900 WHERE name = 'Alice';

步骤 3:用户 B 尝试更新

1
2
3
4
-- 用户 B
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT balance FROM accounts WHERE name = 'Alice'; -- 输出 1000(因为用户 A 还未提交)
UPDATE accounts SET balance = 800 WHERE name = 'Alice'; -- 阻塞等待

步骤 4:用户 A 提交事务

1
2
-- 用户 A
COMMIT;

此时用户 B 的 UPDATE 会报错提示“冲突”,因为两个事务试图修改同一个元组。


📌 小结

技术功能推荐使用场景
BEGIN / COMMIT / ROLLBACK控制事务边界所有涉及多个操作的业务逻辑
ACID保证数据一致性所有生产环境
MVCC高并发无锁访问OLTP、Web 应用
事务隔离级别控制并发行为金融交易、库存管理等关键业务
WAL持久化日志故障恢复、复制、备份

通过本节的学习,你应该已经掌握了 PostgreSQL 中事务控制的基本机制,理解了 ACID 的实现方式以及 MVCC 的工作原理,并能够根据实际业务需求合理设置事务隔离级别。下一节我们将深入讲解“锁机制与死锁检测”,帮助你进一步提升并发控制能力。