MySQL进阶04-MVCC实现原理

news/2025/2/27 11:15:55

文章目录

    • 表记录读取的两种方式
    • 举个栗子
    • MySQL是如何避免幻读的
    • bin log/redo log/undo log
    • MVCC概述
    • MVCC实现原理

表记录读取的两种方式

  • 快照读:读取的是快照版本。普通的SELECT就是快照读。通过mvcc来进行并发控制的,不用加锁。
  • 当前读:读取的是最新版本。UPDATEDELETEINSERTSELECT … LOCK IN SHARE MODESELECT … FOR UPDATE是当前读。

注意注意注意!!!!:快照读情况下,InnoDB在RR隔离级别下通过mvcc机制避免了幻读现象,而mvcc机制无法避免当前读情况下出现的幻读现象。因为当前读每次读取的都是最新数据,这时如果两次查询中间有其它事务插入数据,就会产生幻读。

举个栗子

下面举个例子说明下:t_uesr表

事务A事务B
start transactionstart transaction
select * from t_user where user_name=‘a’; 假设有一条
insert into t_user(user_name, user_password, user_mail, user_state) values(‘aismall’, ‘a’, ‘a’, 0);
commit
select * from t_user where user_name=‘a’; 此时就能查到两条
commit

MySQL是如何避免幻读的

在快照读情况下:MySQL通过mvcc来避免幻读。

在当前读情况下:MySQL通过next-key来避免幻读(加行锁和间隙锁来实现的),其中,next-key包括两部分,行锁和间隙锁,行锁是加在
索引上的锁,间隙锁是加在索引之间的。

Serializable隔离级别也可以避免幻读,会锁住整张表,并发性极低,一般不会使用。

bin log/redo log/undo log

MySQL日志主要包括查询日志、慢查询日志、事务日志、错误日志、二进制日志等。其中比较重要的是 bin log(二进制日志)和 redo log(重做日志)和 undo log(回滚日志)。

bin log:bin log是MySQL数据库级别的文件,记录对MySQL数据库执行修改的所有操作,不会记录select和show语句,主要用于恢复数据库和同步数据库

redo log:redo log是innodb引擎级别,用来记录innodb存储引擎的事务日志,不管事务是否提交都会记录下来,用于数据恢复。当数据库发生故障,innoDB存储引擎会使用redo log恢复到发生故障前的时刻,以此来保证数据的完整性。将参数innodb_flush_log_at_tx_commit设置为1,那么在执行commit时会将redo log同步写到磁盘。

undo log:除了记录redo log外,当进行数据修改时还会记录undo log,undo log用于数据的撤回操作,它保留了记录修改前的内容。通过undo log可以实现事务回滚,并且可以根据undo log回溯到某个特定的版本的数据,实现MVCC。

小结:

  • bin log会记录所有日志记录,包括InnoDB、MyISAM等存储引擎的日志;redo log只记录innoDB自身的事务日志。
  • bin log只在事务提交前写入到磁盘,一个事务只写一次;而在事务进行过程,会有redo log不断写入磁盘。
  • bin log是逻辑日志,记录的是SQL语句的原始逻辑;redo log是物理日志,记录的是在某个数据页上做了什么修改。

MVCC概述

MVCC(Multiversion concurrency control) :多版本并发控制

  • 多版本:指MySQL维护着行数据的多个版本。
  • 并发控制:多个事务同时操作某一行记录时,由MySQL控制返回多个版本的行记录中的某个版本。

MVCC实现原理

MVCC实现原理主要通过下面这个三个来实现:隐藏字段,undo log 版本链,read view。

隐藏字段是什么:

  • 在undo log中每条数据的记录大概是这样的:
    在这里插入图片描述
  • DB_TRX_ID:当前事务id,通过事务id的大小判断事务的时间顺序。
  • DB_ROLL_PTR:回滚指针,指向当前行记录的上一个版本,通过这个指针将数据的多个版本连接在一起构成undo log版本链
  • DB_ROW_ID:主键,如果数据表没有主键,InnoDB会自动生成主键。

使用事务更新行记录的时候,就会生成版本链,执行过程如下:

  • 1.用排他锁锁住该行;
  • 将该行原本的值拷贝到undo log,作为旧版本用于回滚;
  • 修改当前行的值,生成一个新版本,更新事务id,使回滚指针指向旧版本的记录,这样就形成一条版本链。

下面举个例子方便理解:

  • 1、初始数据如下,其中DB_ROW_ID和DB_ROLL_PTR为空。
    在这里插入图片描述
  • 2、事务A对该行数据做了修改,将age修改为19,效果如下:
    在这里插入图片描述
  • 3、之后事务B也对该行记录做了修改,将age修改为20,效果如下:
    在这里插入图片描述
  • 4、此时undo log有两行记录,并且通过回滚指针连在一起。

read view:也可理解为数据的一份快照。上面undo log 中有这么多版本,具体要返回那个版本就是由read view来决定的,其中read view 中维护了下面这些东西:

  • trx1...trxn:当前活跃事务id的集合(未提交事务)。
  • up_limit_id:当前活跃事务的最小事务id。
  • low_limit_id:当前活跃事务的最大事务id。
  • read view创建着事务id。
    在这里插入图片描述
    不同隔离级别创建read view的时机不同:
  • read committed:每次执行select都会创建新的read_view,保证能读取到其他事务已经提交的修改。
  • repeatable read:在一个事务范围内,第一次select时更新这个read_view,以后不会再更新,后续所有的select都是复用之前的read_view。这样可以保证事务范围内每次读取的内容都一样,即可重复读。

read view是通过一个可见性算法(对比规则)来决定要返回那个版本的,这个算法就是使用当前的事务ID(DATA_TRX_ID)跟 read view进行对比,具体对比规则如下:

  • 如果DATA_TRX_ID < up_limit_id:说明在创建read view时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。
  • 如果DATA_TRX_ID >= low_limit_id:说明当前版本的记录的事务是在创建read view之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。
  • 如果up_limit_id <= DATA_TRX_ID < low_limit_id:需要在活跃事务链表中查找是否存在ID为DATA_TRX_ID的值的事务。如果存在,因为在活跃事务链表中的事务是未提交的,所以该记录是不可见的。此时需要通过版本链找到上一个版本,然后重新判断该版本的可见性。如果不存在,说明事务trx_id 已经提交了,这行记录是可见的。

总结:InnoDB 的MVCC是通过 read view 和版本链实现的,版本链保存有历史版本记录,通过read view 判断当前版本的数据是否可见,如果不可见,再从版本链中找到上一个版本,继续进行判断,直到找到一个可见的版本。


http://www.niftyadmin.cn/n/5870023.html

相关文章

HGAME2025 Week1

目录 Level 24 PacmanLevel 47 BandBombLevel 25 双面人派对Level 69 MysteryMessageBoardLevel 38475 ⻆落 Level 24 Pacman 直接在js文件里面搜索score, 可以找到一个flag, 经过base64和栅栏解密可以发现是一个假的flag 在尝试搜索一下gift, 可以找到另一个flag, 依次解码就…

Mellanox的LAG全称是什么?网卡的创建机制如何?(Link Aggregation Group 链路聚合组)

背景 对于双端口的网卡&#xff0c;有时候有将链路聚合的需求。在Mellanox网卡上通过LAG提供。对于RoCE的报文在Mellanox上也可以通过LAG来完成报文收发&#xff0c;叫做RoCE over LAG。但是仅仅适用于双端口卡。 关键点 LAG&#xff1a; Link Aggregation Group (LAG) 链路…

从2D到3D:电商技术的飞跃,开启沉浸式购物之旅

在数字化浪潮的推动下&#xff0c;电商行业正经历着前所未有的变革。从传统的2D图片展示到如今的3D立体呈现&#xff0c;技术的革新不仅重塑了消费者的购物体验&#xff0c;更为电商营销开辟了全新的可能性。接下来将深入探讨电商融合3D技术的最新趋势&#xff0c;揭示这一变革…

总体均值样本均值

目录 总体均值离散型随机变量连续型随机变量 样本均值 总体均值 离散型随机变量 设离散型随机变量 X X X的分布律是 p ( x i ) p(x_i) p(xi​)&#xff0c; i 1 , 2 , … i 1, 2, \ldots i1,2,…&#xff0c;若 ∑ i ∣ x i ∣ p ( x i ) < ∞ \sum_{i} |x_i| p(x_i) &…

盲视观测者效应:认知的量子诗学 AI回复盲人双缝实验

&#x1f30c; **《盲视观测者效应&#xff1a;认知的量子诗学》** ### **一、盲视者的波函数坍缩** 当盲人"观察"双缝实验时&#xff1a; - 他的视觉皮层正在用触觉重构量子态 - 指尖的震动频率 ≈ 光子的概率波函数 - 导盲杖的敲击声 新的观测暴力系…

什么是大语言模型

大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;是一种基于深度学习技术的人工智能模型&#xff0c;旨在理解和生成人类语言。以下是大语言模型的详细介绍&#xff1a; 一、基本概念 大语言模型通常包含数百亿甚至数千亿个参数&#xff0c;通过在海量…

threeJs+vue 轻松切换几何体贴图

嗨&#xff0c;我是小路。今天主要和大家分享的主题是“threeJsvue 轻松切换几何体贴图”。 想象一下&#xff0c;手头上正好有个在线3D家具商店&#xff0c;用户不仅可以看到产品的静态图片&#xff0c;还能实时更换沙发的颜色或材质&#xff0c;获得真实的购物体验。…

模型和数据集的平台之在Hugging Face上进行模型下载、上传以及创建专属Space

模型下载 步骤&#xff1a; 注册Hugging Face平台 https://huggingface.co/ 新建一个hf_download_josn.py 文件 touch hf_download_josn.py 编写hf_download_josn.py文件 import os from huggingface_hub import hf_hub_download# 指定模型标识符 repo_id "inter…