数据库事务的四大特性,通常简称为 **ACID 特性**,是保证事务可靠执行的核心原则

Source

数据库事务的四大特性,通常简称为 ACID 特性,是保证事务可靠执行的核心原则:

原子性(Atomicity):事务是一个不可分割的最小执行单元,其中的所有操作要么全部成功提交,要么全部失败回滚,不存在“部分执行”的状态。由数据库的 undo log(回滚日志) 支持。

一致性(Consistency):事务执行前后,数据库必须从一个合法状态(满足所有约束、触发器、级联等规则)转变为另一个合法状态。这是事务的逻辑正确性保障,由应用逻辑与数据库约束(如主键、外键、唯一性、CHECK 约束等)共同维护。

隔离性(Isolation):多个并发事务之间相互隔离,一个事务的执行不应被其他事务干扰。通过隔离级别(如读未提交、读已提交、可重复读、串行化)和锁机制 / MVCC(多版本并发控制) 实现。

持久性(Durability):一旦事务成功提交(COMMIT),其对数据库的修改将永久保存,即使系统崩溃或断电也不会丢失。由 redo log(重做日志) 和 WAL(Write-Ahead Logging)机制保障。

✅ 补充说明:ACID 是传统关系型数据库(如 MySQL、PostgreSQL、Oracle)的核心设计目标;而在分布式或高并发场景下,部分系统(如某些 NoSQL)可能在 CAP 理论权衡中弱化强一致性(C)或强隔离性(I),转而采用 BASE 理论(基本可用、软状态、最终一致性)。

-- 示例:一个典型的 ACID 事务(以银行转账为例)
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;  -- 扣款
UPDATE accounts SET balance = balance + 100 WHERE id = 2;  -- 入账
COMMIT;  -- 原子提交,确保两步同时生效或同时撤销

MySQL 中的 MVCC(Multi-Version Concurrency Control,多版本并发控制)是 InnoDB 存储引擎实现事务隔离级别的核心机制,尤其在 可重复读(REPEATABLE READ) 隔离级别下发挥关键作用。其核心思想是:不锁住读操作,而是为每个事务提供数据的一致性快照(snapshot),从而避免读写冲突,提升并发性能。

MVCC 的实现基础(InnoDB):

  1. 隐藏字段
    每行记录包含两个隐藏的 6 字节系统列(由 InnoDB 自动维护):

    • DB_TRX_ID:记录最后一次对该行执行 INSERT/UPDATE 的事务 ID;
    • DB_ROLL_PTR(回滚指针):指向该行在 undo log 中的历史版本链(即旧版本数据)。
  2. undo log 版本链
    当事务修改数据时,InnoDB 不直接覆盖原记录,而是将旧值写入 undo log,并通过 DB_ROLL_PTR 将新旧版本串联成链表(从最新到最旧)。这构成了该行的“多版本”。

  3. Read View(一致性视图)
    在事务首次执行 SELECT(快照读)时,InnoDB 创建一个 Read View,其中包含:

    • m_ids:当前活跃(未提交)事务 ID 列表;
    • min_trx_idm_ids 中最小事务 ID;
    • max_trx_id:下一个将被分配的事务 ID(即当前最大已用 ID + 1);
    • creator_trx_id:创建该 Read View 的事务 ID。

    查询时,InnoDB 根据 Read View 判断某版本是否对当前事务可见:

    • row.trx_id < min_trx_id → 该版本由已提交事务生成,可见
    • row.trx_id >= max_trx_id → 该版本由未来事务生成,不可见
    • row.trx_id ∈ m_ids → 该版本由未提交事务生成,不可见
    • row.trx_id == creator_trx_id → 当前事务自己修改的版本,可见

各隔离级别与 MVCC 的关系:

隔离级别 Read View 创建时机 是否复用 Read View 效果说明
READ UNCOMMITTED 不使用 MVCC,直接读最新行(可能脏读) 无快照,不生成 Read View
READ COMMITTED 每次 SELECT 都新建 Read View 每次读都看到最新已提交数据(非重复读)
REPEATABLE READ 仅在第一次 SELECT 时创建 Read View 后续查询复用同一快照 → 实现“可重复读”
SERIALIZABLE 加锁读(如 SELECT … LOCK IN SHARE MODE),退化为行锁/间隙锁 MVCC 基本不生效,靠锁保证串行

关键点

  • 可重复读 ≠ 无幻读:InnoDB 通过 Next-Key Lock(间隙锁+行锁) 解决 RR 级别下的幻读问题(针对当前读,如 SELECT ... FOR UPDATE);而 MVCC 仅保障快照读(普通 SELECT)的可重复性。
  • MVCC 只用于快照读;当前读(带锁读、UPDATE/DELETE)会忽略 Read View,直接访问最新版本并加锁。
-- 示例:RR 级别下 MVCC 行为
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM t WHERE id = 1; -- 创建 Read View,获取快照
-- 此时其他事务更新并提交 id=1 的行
SELECT * FROM t WHERE id = 1; -- 仍返回旧值(复用同一 Read View)
COMMIT;

在这里插入图片描述