
博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌
博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+MySQL+Vue等前后端分离项目,可以在左边的分类专栏找到更多项目。《Uniapp项目案例》有几个有uniapp教程,企业实战开发。《微服务实战》专栏是本人的实战经验总结,《Spring家族及微服务系列》专注Spring、SpringMVC、SpringBoot、SpringCloud系列、Nacos等源码解读、热门面试题、架构设计等。除此之外还有不少文章等你来细细品味,更多惊喜等着你哦
🍅uniapp微信小程序🍅面试题软考题免费使用,还可以使用微信支付,扫码加群。由于维护成本问题得不到解决,可能将停止线上维护。
🍅文末获取联系🍅精彩专栏推荐订阅👇🏻👇🏻 不然下次找不到哟
Java项目案例《100套》
https://blog.csdn.net/qq_57756904/category_12173599.html
uniapp小程序《100套》https://blog.csdn.net/qq_57756904/category_12173599.html
有需求代码永远写不完,而方法才是破解之道,抖音有实战视频课程,某马某千等培训都是2万左右,甚至广东有本科院校单单一年就得3万4年就12万学费,而且还没有包括吃饭的钱。所以很划算了。另外博客左侧有源码阅读专栏,对于求职有很大帮助,当然对于工作也是有指导意义等。在大城市求职,你面试来回一趟多多少少都在12块左右,而且一般不会一次性就通过,还得面试几家。而如果你对源码以及微服务等有深度认识,这无疑给你的面试添砖加瓦更上一层楼。
最后再送一句:最好是学会了,而不是学废了!!
2
MySQL 的 MVCC (Multi-Version Concurrency Control, 多版本并发控制) 是其核心存储引擎 InnoDB 实现高并发、非阻塞读的关键机制。它允许读操作不阻塞写操作,写操作也不阻塞读操作(在特定隔离级别下),从而极大地提升了数据库的并发性能。
以下是 MySQL InnoDB MVCC 的核心要点和工作原理:
-
核心思想:保留数据的历史版本
-
当一行数据被修改时,InnoDB 不会立即覆盖原始数据,而是将原始数据标记为旧版本,并创建一个新版本。
-
同时进行的读操作仍然可以访问到修改发生前的旧版本数据(快照)。
-
数据的多个版本(旧版本)保存在 Undo Log 段中。
-
-
实现基础:隐藏字段
InnoDB 在每一行记录(聚簇索引的叶子节点)中,除了用户定义的列,还添加了三个隐藏的系统字段:
-
DB_TRX_ID
(6 Bytes): 记录最后一次修改 (INSERT 或 UPDATE)该行记录的事务 ID。 -
DB_ROLL_PTR
(7 Bytes): 指向该行记录上一个版本 在 Undo Log 中位置的指针(回滚指针)。利用这个指针可以构建一条该行记录的版本链。 -
DB_ROW_ID
(6 Bytes): 隐含的自增行 ID(Row ID)。如果表没有定义主键,InnoDB 会自动生成一个聚簇索引基于此字段。
-
-
关键组件:Undo Log
-
存储被修改数据的旧版本。
-
当进行
UPDATE
或DELETE
操作时:-
UPDATE
: 将修改前的行数据(包含所有字段)复制到 Undo Log 中,形成一个旧版本记录。然后更新当前行的数据,并将DB_TRX_ID
设置为当前事务 ID,DB_ROLL_PTR
指向刚刚写入 Undo Log 的旧版本记录。 -
DELETE
: InnoDB 实际上并不立即删除数据,而是将其标记为删除(设置一个删除标志)。同时,将删除前的整行数据复制到 Undo Log 中。真正的物理删除(Purge)由后台线程在确定没有任何事务需要访问这些旧版本数据时才进行。
-
-
Undo Log 主要用于:
-
事务回滚 (
ROLLBACK
):通过DB_ROLL_PTR
找到旧版本数据并恢复。 -
实现 MVCC:提供一致性读所需的历史快照。
-
-
-
可见性判断:Read View
-
当一个事务(通常是只读事务或开启了
START TRANSACTION WITH CONSISTENT SNAPSHOT
)执行普通的SELECT
查询(快照读)时,InnoDB 会为该事务生成一个 Read View(读视图)。 -
Read View 决定了该事务能看到数据的哪个版本。它包含以下关键信息:
-
trx_ids
: 生成 Read View 时,系统内所有活跃(已启动但未提交)的读写事务的事务 ID 列表。 -
low_limit_id
: 生成 Read View 时,系统应该分配给下一个事务的 ID 值(即当前最大事务 ID + 1)。 -
up_limit_id
: 活跃事务列表trx_ids
中最小的事务 ID。 -
creator_trx_id
: 创建该 Read View 的事务自身的事务 ID(对于只读事务,该值为 0)。
-
-
可见性规则 :对于版本链中的每一行记录(通过
DB_ROLL_PTR
回溯),使用该行的DB_TRX_ID
和当前事务的 Read View 进行判断:-
如果
DB_TRX_ID
<up_limit_id
:说明该版本是在生成 Read View 之前 就已提交的事务修改的,可见。 -
如果
DB_TRX_ID
>=low_limit_id
:说明该版本是在生成 Read View 之后 才开启的事务修改的(或者就是本事务修改的但未提交),不可见。需要沿着版本链继续查找更旧的版本。 -
如果
up_limit_id
<=DB_TRX_ID
<low_limit_id
:说明该版本是由在生成 Read View 时活跃的事务修改的。-
如果
DB_TRX_ID
在trx_ids
列表中,表示该事务当时活跃(未提交),则该版本不可见,继续找旧版本。 -
如果
DB_TRX_ID
不在trx_ids
列表中,表示该事务在生成 Read View 时已提交 ,则该版本可见。
-
-
如果
DB_TRX_ID
=creator_trx_id
:说明该版本是由本事务 自己修改的,可见。
-
-
事务会沿着版本链(通过
DB_ROLL_PTR
)依次应用这些规则,直到找到第一个对其可见的版本。
-
-
与事务隔离级别的关系
MVCC 主要在 READ COMMITTED (RC) 和 REPEATABLE READ (RR) 隔离级别下发挥核心作用。它们的主要区别在于 Read View 的生成时机:
-
READ COMMITTED (RC):
-
每次执行
SELECT
语句(快照读)时,都会重新生成一个最新的 Read View。 -
因此,它能读取到最新已提交的数据。解决了脏读,但可能出现不可重复读和幻读。
-
-
REPEATABLE READ (RR):
-
在事务中第一次执行
SELECT
语句(快照读)时 生成一个 Read View。在整个事务期间,后续的所有快照读都复用这个第一次生成的 Read View。 -
因此,在同一个事务内,多次读取同一条记录,看到的是同一个历史快照(第一次读时的状态)。解决了脏读和不可重复读。
-
InnoDB 在 RR 级别下还通过 Next-Key Locking(间隙锁)机制来防止幻读(MVCC 的快照读本身不能完全防止幻读,因为新插入的数据可能不在快照中,但当前读会加锁阻止插入)。
-
-
-
快照读 vs. 当前读
-
快照读 (Snapshot Read):
-
普通的
SELECT
语句(不加FOR UPDATE
或LOCK IN SHARE MODE
)。 -
使用 MVCC 机制,读取历史版本(Read View 决定),不加锁(理论上,可能遇到历史数据被 Purge 清理的情况,但通常不影响一致性)。
-
目的是提供一致性的非锁定读。
-
-
当前读 (Current Read):
-
SELECT ... FOR UPDATE
-
SELECT ... LOCK IN SHARE MODE
-
UPDATE
,DELETE
,INSERT
-
读取的是数据的最新提交版本。
-
会加锁(记录锁、间隙锁、Next-Key 锁)以保证操作的正确性和防止并发冲突。
-
目的是处理当前最新的数据状态并进行修改。
-
-
-
Purge 操作
-
随着事务的提交,不再需要访问的旧版本数据(Undo Log)会变得多余。
-
InnoDB 的后台线程 Purge Thread 会负责清理这些不再被任何 Read View 依赖的旧版本数据和 Undo Log 空间。这个过程称为 Purge。
-
长事务会阻止 Purge 线程清理它可能需要的旧版本数据,导致 Undo Log 膨胀,这是需要注意的。
-
总结 MySQL InnoDB MVCC 的优势:
-
高并发读: 读操作通常不需要加锁,不会被写操作阻塞。
-
非阻塞写: 写操作通常只需要锁定当前处理的行(或间隙),不会阻塞其他行的读操作(快照读)。
-
一致性读: 在不同隔离级别(RC/RR)下提供不同强度的一致性视图,避免脏读,解决不可重复读(RR)。
-
高效回滚: Undo Log 天然支持事务回滚。
需要注意:
-
MVCC 主要在 READ COMMITTED 和 REPEATABLE READ 隔离级别下有效。READ UNCOMMITTED 总是读最新数据(可能脏读),SERIALIZABLE 会对所有读加锁,不使用 MVCC 的快照读。
-
MVCC 会增加存储开销(Undo Log 存储历史版本)和 CPU 开销(构建和遍历版本链)。
-
理解
DB_TRX_ID
,DB_ROLL_PTR
, Undo Log, Read View 以及可见性规则是掌握 MVCC 的关键。
通过 MVCC,MySQL InnoDB 在保证事务隔离性的同时,极大地提高了数据库的并发处理能力,是现代 OLTP 应用高性能的重要基石。
3