当前位置: 代码网 > it编程>数据库>Mysql > MySQL怎么实现原子性的流程详解(以UPDATE为例)

MySQL怎么实现原子性的流程详解(以UPDATE为例)

2025年08月18日 Mysql 我要评论
前言首先,应该想到innodb存储引擎,因为它是mysql默认支持事务的引擎。myisam不支持事务,所以可能不适用。实现原子性关键在于undo log,undo log记录了sql执行之前的状态,以

前言

首先,应该想到innodb存储引擎,因为它是mysql默认支持事务的引擎。myisam不支持事务,所以可能不适用。实现原子性关键在于undo log,undo log记录了sql执行之前的状态,以便回滚恢复数据。

另外,事务的提交和回滚机制也很重要。当用户执行一个事务时,所有的修改操作会先记录到undo log中,如果事务成功提交,这些修改才会被持久化到磁盘;如果事务回滚,系统会利用undo log将数据恢复到事务开始前的状态。

还需要考虑redo log,虽然redo log主要是保证持久性,但它在事务提交时也起到关键作用,确保即使系统崩溃,已提交的事务修改也不会丢失。但现在问题是原子性,所以可能更侧重于undo log和事务的回滚机制。

还有一方面,锁机制也可能有关联。比如,在事务执行期间,相关的数据会被加锁,防止其他事务干扰,这有助于保证事务的原子性,因为在一个事务未完成前,其他事务不能修改相同的数据,从而避免中间状态被看到。

undo的工作流程大致为,当事务开始时,innodb会生成一个undo log记录旧值。如果在事务中执行了insert、update或delete操作,这些操作的反向操作会被记录到undo log中。如果事务需要回滚,就利用这些undo log来撤销更改。

还有一个点是,原子性不仅包括回滚,还包括提交时的原子性。在提交时,所有修改必须一次性写入到redo log和binlog中,确保即使系统崩溃,也能通过日志恢复事务的状态。这里可能涉及到两阶段提交(2pc)协议,协调redo log和binlog的写入,保证两者的日志一致性,从而确保事务的原子性。

在此之前必须了解原子性的基本概念。

总结一下,mysql实现原子性的关键点包括:undo log记录修改前的数据状态,用于回滚;事务提交时的两阶段提交机制,确保日志的原子性写入;以及锁机制保证事务执行期间的隔离性,间接支持原子性。

mysql 通过 undo log(回滚日志)、事务提交机制 和 innodb 存储引擎的原子性设计 来实现事务的原子性,确保事务中的操作要么全部成功,要么全部回滚。下面章节是具体实现原理。

一、原子性的定义

原子性(atomicity)要求事务是一个不可分割的操作单元,事务中的操作要么全部成功提交,要么全部失败回滚,不会停留在中间状态。

二、实现原子性的核心技术

2.1. undo log(回滚日志)

  • 作用:记录事务修改前的数据状态,用于事务回滚。

  • 实现细节:

    • 每个事务开始时,innodb 会为其生成一个 undo log segment。
    • 对数据的增删改操作(insert/delete/update)会先记录到 undo log 中:
      • insert:记录新插入数据的主键,回滚时根据主键删除。
      • delete:记录删除前的完整数据,回滚时重新插入。
      • update:记录修改前的旧值,回滚时恢复旧值。
  • 生命周期:

    • 事务提交后,undo log 不会立即删除,而是等待可能存在的其他事务(如 mvcc 读)不再需要时,由后台线程清理。

2.2 事务提交与回滚机制

  • 事务提交(commit):
    • 将事务的所有修改写入内存中的 buffer pool。
    • 将修改的 redo log(重做日志)写入磁盘(innodb_flush_log_at_trx_commit=1 时强制刷盘)。
      标记事务为已提交,释放相关锁资源。
  • 事务回滚(rollback):
    • 根据 undo log 中的记录反向执行操作(如删除新增数据、恢复旧值)。
    • 清理事务相关的锁和 undo log。

2.3. 崩溃恢复(crash recovery)

  • 若事务未提交时 mysql 崩溃:

    • 重启后,通过 undo log 回滚未提交的事务。
  • 若事务已提交但数据未持久化到磁盘:

    • 通过 redo log 重放已提交的事务操作,确保数据持久性。

三、原子性的实现流程(以 update 为例)

1.事务开始:

start transaction;

2.执行 update 操作:

update users set balance = balance - 100 where id = 1;

innodb 将旧值 balance = 200 写入 undo log。

3.事务提交:

commit;

写入 redo log 并刷盘,标记事务完成。

4.事务回滚:

rollback;
  • 根据 undo log 将 balance 恢复为 200。

四、关键设计与优化

  1. 两阶段提交(2pc)
  • 协调 redo log 和 binlog:
    • prepare 阶段:写入 redo log,标记为 prepare 状态。
    • commit 阶段:写入 binlog,标记 redo log 为 commit 状态。
  • 作用:确保事务日志的一致性,即使崩溃也能通过日志恢复原子性
  1. mvcc(多版本并发控制)
  • 依赖 undo log:为每个读操作提供事务开始时的数据快照。
  • 实现原子性隔离:确保事务回滚时,其他事务不会看到中间状态。
  1. 锁机制
  • 行锁、表锁:在事务执行期间锁定资源,防止其他事务干扰。
  • 隐式锁:通过 undo log 的可见性判断实现非阻塞读。

五、原子性与其他 acid 属性的协作

六、验证原子性的示例

  • 场景:转账操作(a 转 100 给 b)
start transaction;
update accounts set balance = balance - 100 where user = 'a';
update accounts set balance = balance + 100 where user = 'b';
commit;
  • 原子性保证:
    • 若执行到第 2 步后崩溃,事务未提交,undo log 会回滚 a 的余额。
    • 若执行到 commit 时崩溃,重启后通过 redo log 重放完整事务。

七、总结

mysql 通过以下机制实现原子性:

1.undo log:记录事务前的数据状态,支持回滚。

2.redo log 和两阶段提交:确保已提交事务的持久性和日志一致性。

3.崩溃恢复机制:通过日志回滚未完成事务或重放已提交事务。

4.锁与 mvcc:隔离事务操作,避免中间状态被其他事务读取。

这些机制共同保障了事务的原子性,使得 mysql 在高并发和数据一致性场景下表现可靠。

到此这篇关于mysql怎么实现原子性流程(以update为例)的文章就介绍到这了,更多相关mysql实现原子性内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com