事务王国生存指南:隔离级别与锁实现的降维打击

一、ACID 实现原理

  1. 原子性(Atomicity)

    • 通过 undo log 实现:事务回滚时,逆向执行 undo log 中的操作。
    • 若事务失败,数据库会撤销所有未提交的修改。
  2. 一致性(Consistency)

    • 由应用层和数据库约束(如唯一索引、外键)共同保证。
    • 事务执行前后数据库必须满足所有预定义的业务规则。
  3. 隔离性(Isolation)

    • 通过锁机制或 MVCC(多版本并发控制)实现。
    • 不同隔离级别对应不同锁策略(如 READ COMMITTED 使用行级锁)。
  4. 持久性(Durability)

    • 依赖 redo log:事务提交时,修改先写入 redo log,再异步刷盘。
    • 崩溃恢复时通过 redo log 重放未持久化的操作。

二、隔离级别与问题

隔离级别 脏读 不可重复读 幻读 实现方式
READ UNCOMMITTED ✔️ ✔️ ✔️ 无锁
READ COMMITTED ✖️ ✔️ ✔️ 行级锁 + MVCC
REPEATABLE READ ✖️ ✖️ ✔️ MVCC + 间隙锁(如 MySQL)
SERIALIZABLE ✖️ ✖️ ✖️ 表级锁或严格串行化调度

三、MVCC 核心机制

  1. 版本链

    • 每行数据包含隐藏字段:DB_TRX_ID(事务ID)、DB_ROLL_PTR(回滚指针)。
    • 通过 undo log 构建历史版本链。
  2. ReadView

    • 事务启动时生成活跃事务列表,用于判断数据可见性。
    • 可见性规则
      • DB_TRX_ID 小于最小活跃事务ID → 可见
      • DB_TRX_ID 在活跃事务列表中 → 不可见
      • DB_TRX_ID 大于最大事务ID → 不可见
  3. 隔离级别差异

    • READ COMMITTED:每次查询生成新 ReadView
    • REPEATABLE READ:事务首次查询时生成 ReadView

四、悲观锁 vs 乐观锁

特性 悲观锁 乐观锁
实现方式 数据库锁(如 SELECT ... FOR UPDATE 版本号/时间戳 + CAS 机制
适用场景 高并发写冲突 低冲突场景
性能影响 锁竞争可能引发阻塞 无锁,但需处理重试逻辑

实现示例

  1. 悲观锁(MySQL)

    sql 复制代码
    BEGIN;
    SELECT * FROM table WHERE id=1 FOR UPDATE; -- 加行锁
    UPDATE table SET value=100 WHERE id=1;
    COMMIT;
  2. 乐观锁(Java)

    java 复制代码
    // 更新时检查版本号
    UPDATE table SET value=100, version=version+1 
    WHERE id=1 AND version=old_version;
    // 若影响行数为0,则重试或抛异常

五、关键设计权衡

  1. 隔离级别选择REPEATABLE READ 平衡了性能与一致性(如 MySQL 默认级别)。
  2. 锁粒度 :行级锁(InnoDB)比表级锁并发度高,但管理成本更高。
  3. MVCC 优势:读操作不阻塞写,提升并发性能。

实际选型需结合业务场景(如高频更新 vs 低频冲突)和数据库特性(如 MySQL 的间隙锁)。

相关推荐
wsaaaqqq5 分钟前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
鱼人7 分钟前
响应式三巨头:rem / vw / em 深度对比,移动端到底该选谁?
后端
小强198811 分钟前
Grid 网格布局实战:快速实现复杂网页排版
后端
胡志辉11 分钟前
深入浅出 call、apply、bind
前端·javascript·后端
长大198811 分钟前
Flex 布局完整教程:告别浮动,拥抱万能弹性布局
后端
iccb10131 小时前
5年,一个程序员是如何把私有化在线客服系统做到第一名的
前端·后端·github
Rust研习社1 小时前
这 8 个 Rust 学习资源值得每个新手收藏起来
后端·rust·编程语言
Nturmoils1 小时前
ksql 里这些命令不用加分号,但日常查库少不了
后端
假如让我当三天老蒯1 小时前
回归基本功:Map/Set 与 WeakMap/WeakSet 的区别
前端·面试
Dilee1 小时前
Spring AI 接 RAG 最小 Demo:DeepSeek、Ollama、SimpleVectorStore 一次跑通
后端