MySQL事务与隔离级别深度解析

一、 事务基础概念

1. 什么是事务

事务(Transaction)是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作。事务具有以下四个关键特性(ACID):

  • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成

  • 一致性(Consistency):事务执行前后,数据库从一个一致状态变到另一个一致状态

  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务

  • 持久性(Durability):事务一旦提交,其结果就是永久性的

2. MySQL中的事务控制语句

START TRANSACTION;  -- 或 BEGIN
-- 执行SQL操作
COMMIT;            -- 提交事务
ROLLBACK;          -- 回滚事务

二、事务隔离级别详解

1. 四种标准隔离级别

MySQL支持四种事务隔离级别,控制不同事务之间的可见性:

隔离级别脏读不可重复读幻读说明
READ UNCOMMITTED(读未提交可能可能可能最低隔离级别
READ COMMITTED(读已提交不可能可能可能大多数数据库默认级别
REPEATABLE READ(可重复读不可能不可能可能MySQL默认级别
SERIALIZABLE(序列化不可能不可能不可能最高隔离级别

2. 并发问题说明

  • 脏读(Dirty Read):读取到其他事务未提交的数据

  • 不可重复读(Non-repeatable Read):同一事务内多次读取同一数据结果不同

  • 幻读(Phantom Read):同一事务内多次查询返回不同的行集合

3. 隔离级别设置与查看

-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 查看当前隔离级别
SELECT @@transaction_isolation;

三、各隔离级别实现机制

1. READ UNCOMMITTED

实现方式:不加锁,直接读取最新数据(包括其他事务未提交的)

问题示例:

-- 事务1
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- 事务2(READ UNCOMMITTED)
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1; -- 可能读取到事务1未提交的修改

2. READ COMMITTED

实现方式:使用MVCC(多版本并发控制),每个语句开始时创建快照

特点:

  • 解决脏读问题
  • 使用行锁防止写冲突 问题示例:
-- 事务1
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1; -- 第一次读取

-- 事务2
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 事务1
SELECT balance FROM accounts WHERE id = 1; -- 第二次读取结果可能不同(不可重复读)

3. REPEATABLE READ(MySQL默认)

实现方式:

  • 事务开始时创建一致性视图

  • 使用MVCC和间隙锁(Gap Lock)防止幻读 特点:

  • 解决脏读和不可重复读

  • 在MySQL中通过间隙锁也解决了大部分幻读问题

示例:

-- 事务1
START TRANSACTION;
SELECT * FROM accounts WHERE balance > 1000; -- 第一次查询

-- 事务2
START TRANSACTION;
INSERT INTO accounts(id, balance) VALUES(11, 1500);
COMMIT;

-- 事务1
SELECT * FROM accounts WHERE balance > 1000; -- 第二次查询结果相同(无幻读)

4. SERIALIZABLE

实现方式:

  • 所有SELECT语句自动转为SELECT … FOR SHARE
  • 使用严格的锁机制实现串行化

特点:

  • 完全串行执行,性能最低
  • 解决所有并发问题

四、MySQL中的MVCC机制

多版本并发控制(Multi-Version Concurrency Control)是InnoDB实现隔离级别的核心技术:

  1. 隐藏字段
    1. DB_TRX_ID:最近修改事务ID
    2. DB_ROLL_PTR:回滚指针
    3. DB_ROW_ID:行ID
  2. Undo日志:存储数据修改前的版本
  3. ReadView:决定事务能看到哪些版本的数据

五、Laravel中的事务实践

1. 基本事务使用

DB::transaction(function () {
    $account = Account::find(1);
    $account->balance += 100;
    $account->save();
    
    Payment::create([
        'account_id' => 1,
        'amount' => 100
    ]);
});

2. 手动控制事务

DB::beginTransaction();

try {
    $order = Order::create([...]);
    
    Inventory::where('product_id', $productId)
        ->decrement('quantity', $quantity);
    
    DB::commit();
} catch (\Exception $e) {
    DB::rollBack();
    // 错误处理
}

3. 设置隔离级别

DB::transaction(function () {
    DB::statement('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');
    
    // 业务逻辑
}, 3); // 尝试3次