当前位置: 首页 > news >正文

mysql mvcc机制详解

什么是当前读、快照读?

当前读

当前读指的是读取数据的​​最新提交版本。底层是通过对数据加锁加锁实现的

当前读sql语句有:

  • select    lock in share mode
  • select    for update
  • insert
  • update
  • delete

快照读

快照读指的是读取数据在某个时间点的​​快照(版本)​​,而不是数据的最新版本

快照读sql语句:普通selcet语句。底层是利用mvcc机制实现的


MVCC是什么?

mvcc就是多版本并发控制。多版本:指mysql维护着行数据的多个版本。

并发控制:在多个事务同时操作某一行记录时,mysql控制返回多个版本的行记录中的某个版本

用来解决什么问题?

用来解决读写冲突问题。

数据库(普通select语句)并发事务时会出现脏读、不可重复读、幻读问题,也需要利用mvcc机制来解决。

流程:一条select语句来查询数据,但是查询的数据有多个版本,这时就要选择其中的某一个版本返回

数据隔离级别和并发问题

脏读 (Dirty Read)、不可重复读 (Non-Repeatable Read) 和 幻读 (Phantom Read)​​ 是数据库事务并发执行时,在没有采取足够隔离措施的情况下,会产生的三类典型问题。

mvcc机制实现了隔离级别,可以解决这三类并发问题

脏读

要解决脏读,就得上读已提交的隔离级别

得保证一个事务只能读取到其他事务已经提交的数据,没提交的就不该读取到

不可重复读

解决不可重复读问题,就得上读已提交隔离级别

一个事务第一次读取之后,后面读取得每一次数据都应该和第一次读取的一样

那就得维护一份数据的多个版本

每个事务修改一次就生成一个新版本,让不同事务读取不同的版本

在读已提交的得隔离级别下,让事务去读已经提交的数据版本,就可以避免脏读

在不可重复读的隔离级别下,让事务每次读到同一个版本的数据,这样每次读到的都是一样的了,就避免的不可重复读的问题

把修改的数据版本记录到undo log中,给表加一个隐藏字段,叫回滚指针

回滚指针指向undolog日志,日志记录了该表的修改记录的各个版本

利用回滚指针将历史版本串联成一个列表,想读哪个,查找即可

那一个事务来查数据,怎么知道要查哪个版本的数据呢?

所以要为每个事务分配一个id,事务id自增分配。通过对比事务id的大小,就知道哪个事务创建的早、哪个晚,记录哪些事务提交了,哪些未提交,让提交的早的事务不要看提交的比较晚的数据即可。所以要给表加上隐藏字段修改数据的事务id,谁修改了这条数据,就把对应的事务id记录下来

readview:4个重要字段:比较复杂,利用数轴来看

记住作用:就是决定在多个版本中,到底该读哪一个版本

undolog记录数据版本

readview去判断这个数据版本对当前事务的可见性

MVCC怎么实现的?

隐藏字段、undolog版本链、readview

undolog版本链、readview是怎么回事?

四种隔离级别怎么实现的

读未提交

不加任何读锁实现的。(假设:我现在在读这条数据,加了读锁,别人就不能修改。不加读锁,别人就可以修改我在读的数据)

读操作不加锁,就可以直接读取最新版本的数据,即使这些数据被其他事务用排他锁锁住(脏读)

会发生:脏读、不可重复读、幻读

读已提交

可以基于锁实现也可以基于mvcc实现(mvcc更常见)

mvcc的实现原理:

每个​​语句​​开始时都会生成一个新的快照(读视图readview)。

一个 Read View主要包含以下核心内容:

  1. ​​m_ids​​: 一个列表,记录了在​​本 Read View创建时​​,系统中所有​​活跃的(尚未提交的)事务​​的事务 ID
  2. ​​min_trx_id​​: 记录 m_ids列表中最小的那个事务 ID。
  3. ​​max_trx_id​​: 记录在​​本 Read View创建时​​,系统已经分配的下一个事务 ID(即当前最大事务 ID + 1)。
  4. ​​creator_trx_id​​: 创建这个 Read View的事务自己的 ID(只有该事务自己有写操作时,这个值才不为空)。

每次查询看到的都是这个​​语句级快照​​的最新已提交数据。所以在一个事务内,两次相同的查询可能会看到不同的数据(不可重复读)。

可重复读

串行化

读未提交怎么实现?

不用管

串行化:加锁

可重复读怎么实现?(复用readview和mvcc机制)

可重复读会在第一次select时生成一个readview,通过readview判断应该读哪个数据

读已提交怎么实现?

每次select时就会生成一个新的readview

http://www.dtcms.com/a/354382.html

相关文章:

  • 期权交易中的“道”:从《道德经》中汲取投资智慧
  • RHEL9部署MySQL数据库及数据库的基本使用(增删改查,数据备份恢复)
  • 基于SpringBoot的社区儿童疫苗接种预约系统设计与实现(代码+数据库+LW)
  • Vue将内容生成为二维码,并将所有二维码下载为图片,同时支持批量下载(下载为ZIP),含解决一次性生成过多时页面崩溃解决办法
  • 【雅思020】Opening a bank account
  • C语言二级考试环境配置教程【window篇】
  • 能源行业数据库远程运维安全合规实践:Web化平台的落地经验
  • 【系统分析师】高分论文:论快速应用开发方法及应用
  • Linux初始——基础指令篇
  • Libvio 访问异常排查指南​
  • List | 常见的List实现类(ArrayList、LinkedList、Vector)以及ArrayList源码解读
  • 【Redis】数据分片机制和集群机制
  • 8.28 模拟|双指针
  • 零基础-力扣100题从易到难详解(持续更新1-10题)
  • Windows 命令行:rmdir 命令
  • Qt 6 与 Qt 5 存在的兼容性差异
  • C# 数组C# 多维数组
  • QML(2) - Qt 中如何注册一个 C++ 类到 QML
  • MySQL的类split方法实现
  • Java表格处理详解以及结合实际项目使用
  • WebStrom-如何设置前端项目快捷启动
  • 29. String, StringBuffer,StringBuilder 的区别是什么
  • 统一虚拟试穿框架OmniTry:突破服装局限,实现多品类可穿戴物品虚拟试穿无蒙版新跨越。
  • 【小白笔记】网速
  • TypeScript:完整的函数类型书写方式
  • 【开题答辩全过程】以超市管理系统为例,包含答辩的问题和答案
  • Linux 系统核心调优:CPU、磁盘 I/O、网络与内核参数实战
  • 流行蝴蝶剑高清重制版Windows10可玩!
  • 小程子找Bug之for循环的初始化表达类型
  • 【美团】放它一马