侧边栏壁纸
博主头像
月伴飞鱼 博主等级

行动起来,活在当下

  • 累计撰写 126 篇文章
  • 累计创建 31 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

MySQL事务ACID是如何实现的?

月伴飞鱼
2025-03-16 / 0 评论 / 1 点赞 / 9 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

在 MySQL 的 InnoDB 存储引擎中,事务需要满足 ACID(原子性 Atomicity、一致性 Consistency、隔离性 Isolation、持久性 Durability)特性。

MySQL 主要通过 Undo Log、Redo Log、Binlog、MVCC、锁机制 等手段来实现 ACID。

1. 原子性(Atomicity)

原子性指的是事务中的所有操作要么全部成功,要么全部失败回滚

如何实现原子性?

通过 Undo Log(撤销日志)

  • 事务开始前,MySQL 记录修改前的数据快照Undo Log

  • 如果事务回滚,MySQL 使用 Undo Log 还原数据,恢复到事务前的状态。

示例

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
ROLLBACK; -- 触发原子性回滚
  • 执行 ROLLBACK,Undo Log 用于恢复 balance 的原始值。

原子性保证

  • 如果事务失败(崩溃、错误等),Undo Log 确保数据可以回滚。

  • 事务要么完全执行,要么完全回滚,不会导致部分更新的状态。

2. 一致性(Consistency)

一致性指的是事务执行后,数据库应从一个一致状态转换到另一个一致状态

如何实现一致性?

通过数据库约束

  • 主键约束(PRIMARY KEY)

  • 唯一约束(UNIQUE)

  • 外键约束(FOREIGN KEY)

  • 非空约束(NOT NULL)

  • 检查约束(CHECK)

通过 ACID 机制共同保障

  • 原子性:事务失败时,Undo Log 确保数据回滚,避免数据异常。

  • 隔离性:多个事务并发时,MVCC 和锁机制保证数据不冲突。

  • 持久性:Redo Log 确保已提交的事务不会丢失。

示例

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

保证一致性的机制

  • 事务提交前,不能让外部看到中间状态(事务隔离)。

  • 事务提交后,所有更改必须是合法的(事务持久性)。

  • 如果失败,则回滚所有操作,恢复到一致状态

3. 隔离性(Isolation)

隔离性指的是多个事务并发执行时,互不干扰,避免脏读、不可重复读、幻读等问题。

如何实现隔离性?

通过事务隔离级别

隔离级别

解决问题

实现方式

读未提交(Read Uncommitted)

可能发生脏读

无隔离

读已提交(Read Committed)

解决脏读

每次查询生成新 ReadView

可重复读(Repeatable Read)

解决脏读、不可重复读

事务开始时生成 ReadView

串行化(Serializable)

解决所有问题(但性能低)

事务间强制加锁,串行执行

通过 MVCC(多版本并发控制)

  • MVCC 通过 Undo Log 维护多个版本的数据快照,让事务可以读取历史数据,而不会被并发事务影响。

  • 快照读(ReadView):在事务开始时获取一个一致性视图,让同一个事务内的所有查询看到相同的数据版本。

通过锁机制

  • 共享锁(S 锁,Shared Lock):多个事务可以共享读,但不能修改。

  • 排他锁(X 锁,Exclusive Lock):事务独占写,不允许其他事务读写。

  • 间隙锁(Gap Lock):解决幻读,防止插入新数据。

示例

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT balance FROM accounts WHERE id = 1; -- 读取时创建 ReadView
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
  • 隔离性保证

    • 事务在 SELECT 之后即使有其他事务更新 balance,事务内的 balance 值不会变化。

4. 持久性(Durability)

持久性指的是事务提交后,数据必须永久保存,即使系统崩溃,数据也不会丢失

如何实现持久性?

通过 Redo Log(重做日志)

  • 事务执行时,先将变更写入 Redo Log,但不立即写入磁盘。

  • 事务提交时,刷新 Redo Log 到磁盘,确保数据不会丢失。

  • 系统崩溃时,使用 Redo Log 恢复数据,确保事务数据持久化。

通过 Binlog(归档日志)

  • MySQL 主从复制 依赖 Binlog,确保事务提交后数据不会丢失。

  • 在崩溃恢复时Binlog 可以用来重放事务。

示例

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;  -- 事务提交,刷新 Redo Log
  • 事务提交后,数据持久化到磁盘,确保不会丢失

5. MySQL 事务 ACID 的实现总结

ACID 特性

实现机制

原子性(Atomicity)

Undo Log(回滚日志)

一致性(Consistency)

事务 ACID 机制共同保障 + 约束(外键、主键等)

隔离性(Isolation)

事务隔离级别 + MVCC + 锁机制

持久性(Durability)

Redo Log(崩溃恢复)+ Binlog(数据复制)

6. MySQL ACID 机制优化建议

提高事务持久性

SET GLOBAL innodb_flush_log_at_trx_commit = 1;  -- 每次提交时刷新 Redo Log
SET GLOBAL sync_binlog = 1;  -- 事务提交时同步写入 Binlog

优化事务隔离性

  • OLTP 业务:使用 READ COMMITTED,避免间隙锁,提高并发能力。

  • 金融业务:使用 REPEATABLE READ 确保数据一致性。

减少 Undo Log 开销

  • 避免长事务:长事务会导致 Undo Log 过大,占用大量存储。

  • 使用合适的事务隔离级别,避免不必要的锁等待。

优化数据一致性

  • 避免隐式提交:某些 DDL 语句(如 ALTER TABLE)会导致事务隐式提交,应注意事务边界。

7. 结论

MySQL 的事务 ACID 主要通过 日志(Undo Log、Redo Log、Binlog)、MVCC、事务隔离级别、锁机制 来实现:

  • 原子性 依赖 Undo Log,保证事务失败时数据回滚。

  • 一致性 依赖 ACID 机制和数据库约束,确保事务执行后数据库状态正确。

  • 隔离性 依赖 MVCC + 锁机制,确保事务之间互不干扰。

  • 持久性 依赖 Redo LogBinlog,保证崩溃恢复能力。

公众号.png

1
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
    1. 支付宝打赏

      qrcode alipay
    2. 微信打赏

      qrcode weixin
博主关闭了所有页面的评论