mysql MVCC的实现原理是怎么样的?
2 个回答
今朝有酒今朝醉,明日愁来明日愁。古剑飞### MVCC 的实现原理 MVCC(多版本并发控制,Multi-Version Concurrency Control)的目的是通过维护数据的多个版本,实现高效的并发控制,解决读写冲突。其实现原理主要依赖于以下几个方面: #### 1. 记录中的三个隐式字段 在 MVCC 实现中,每条记录中通常包含以下三个隐式字段: - **数据版本号**:记录每次修改时的版本号。 - **事务 ID**:记录创建或修改该记录的事务 ID。 - **删除标记**:记录删除该记录的事务 ID。 这些隐式字段用于管理和追踪每条记录的多个版本,从而支持并发读写。 #### 2. undo 日志 - **作用**:undo 日志记录了每次数据修改前的旧值。当事务回滚时,可以通过 undo 日志将数据恢复到修改前的状态。 - **实现**:每次对数据进行修改时,系统会生成一条 undo 日志,记录修改前的数据状态。这些日志会存储在数据库的 undo 表空间中。 - **多版本存储**:通过 undo 日志,数据库可以维护每条记录的多个版本,从而支持事务读取其开始前的数据快照。 #### 3. Read View - **作用**:Read View 是事务开始时数据库的一个快照,记录了当前活跃事务的 ID 列表和最小、最大事务 ID。 - **实现**:当事务开始时,数据库会生成一个 Read View,包含当前所有活跃事务的 ID。读取操作会根据这个快照来决定可见的数据版本。 - **版本可见性判断**: - 如果记录的版本号小于 Read View 中的最小事务 ID,则该记录对当前事务可见。 - 如果记录的版本号大于 Read View 中的最大事务 ID,则该记录对当前事务不可见。 - 如果记录的版本号在 Read View 的活跃事务列表中,则该记录对当前事务不可见。 ### MVCC 的工作流程 1. **事务开始**: - 生成一个 Read View,记录当前活跃事务的 ID 列表和最小、最大事务 ID。 2. **读操作**: - 读取操作会根据 Read View 判断记录的版本是否对当前事务可见。只读取可见的记录版本,确保数据一致性。 3. **写操作**: - 每次写操作都会生成新的记录版本,并在记录中更新数据版本号和事务 ID,同时生成对应的 undo 日志。 4. **事务提交**: - 事务提交后,新的数据版本生效,更新 Read View 的活跃事务列表。 5. **事务回滚**: - 通过 undo 日志将数据恢复到修改前的状态,撤销未提交的修改。 ### 总结 MVCC 通过三个隐式字段、undo 日志和 Read View 的配合,实现了高效的多版本并发控制。它能够在不使用锁的情况下,实现并发读写操作,解决读写冲突,保证数据的一致性和事务的隔离性。发布于 2022-12-20 16:48 •IP属地 贵州举报评论收藏
你爱你的玫瑰是因为你在你的玫瑰上花了太多的时间!吴敏mvcc主要适用于可重复读,可以解决幻读的问题。 innodb在解决幻读的问题主要是通MVVC 多版本并发版本控制来实现的。 就是每一行数据中额外保存两个隐藏的列: 插入或上次更新该行的事务ID(删除也被认为是一次更新,只不过在代表删除的更新操作中,行中的特殊位被设置为将其标记为已删除。这个事务ID可以认为是数据行的修改版本号。) 回滚指针(指向undo log中用于事务回滚的日志记录)。 具体流程: **1.插入操作** 每次开始事务时,会对系统版本号+1作为当前事务的版本号。 插入数据后,将事务的版本号作为数据行的创建版本号。 **2.删除操作** 在使用SQL语句删除行时,并不会立即将其从数据库中物理删除,只会将其标记为删除,并且修改更新该行的事务ID。(InnoDB只会在丢弃为删除而编写的undo log日志记录时,才物理删除相应的行及其索引记录。此删除操作称为purge,它非常快,通常花费与执行删除操作的SQL语句相同的时间顺序。) **3.或更新操作** 将当前的事务版本号作为数据行的更新版本号。 **4.查询操作** 数据行要被查询出来必须满足两个条件, 数据行没有标记为删除或者标记为删除但是删除的事务ID>当前事务ID的数据(否则数据已经被标记删除了) 更新事务ID<=当前事务ID的数据(否则数据是后面的事务创建出来的,或者是被修改过的,那么需要去undo log中找上次的快照数据。) 如果查询时,该行数据被加了X锁,那么读数据的事务不会进行等待,而是会根据该行数据中的回滚指针undo log日志中读之前版本的数据(这里存储的数据本身是用于回滚的),在可重复读的隔离级别下,从undo log中读取的数据总是事务开始时的快照数据(也就是版本号小于当前事务id的数据),在提交读的隔离级别下,从undo log中读取的总是最新的快照数据。 参考文档: [https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html](https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html) [https://blog.csdn.net/qq_41652863/article/details/98800650](https://blog.csdn.net/qq_41652863/article/details/98800650)发布于 2022-02-11 18:48 •IP属地 江西举报评论收藏
公众号进入网站体验更佳

