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

一、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 的间隙锁)。

相关推荐
这里有鱼汤几秒前
老祖宗没骗我,我把《周易》六十四卦丢给了大A股,市场居然回应了我
后端·python
Bob99981 分钟前
Logitech (罗技)单通道、双通道与6通道 Unifying 接收器:USB ID、功能与实用性解析
java·网络·c++·python·stm32·单片机·嵌入式硬件
芝士加2 分钟前
最全301/302重定向指南:从SEO到实战,一篇就够了
前端·javascript·面试
陈随易3 分钟前
2025年100个产品计划之第7个(树图) - 目录结构生成工具
前端·后端·程序员
Victor3563 分钟前
MySQL(55)什么是覆盖索引?
后端
用户13151738256153 分钟前
##将发红包抽象成handler模型
面试
程序员爱钓鱼4 分钟前
Go语言依赖管理与版本控制-《Go语言实战指南》
后端·go·排序算法
义达7 分钟前
Anycast从原理到实践
后端·架构·云计算
Victor3567 分钟前
MySQL(56)什么是复合索引?
后端
海尔源码8 分钟前
Java 的基础代码示例
java