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

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.xdnf.cn/news/19099.html

相关文章:

  • Java全栈开发面试实战:从基础到微服务架构的深度解析
  • IntelliJ IDEA Debug 模式功能指南
  • 替身演员的艺术:pytest-mock 从入门到飙戏
  • 寻找AI——初识墨刀AI
  • 极海发布APM32F425/427系列高性能MCU:助力工业应用升级
  • Ansible模块实战,操作技巧
  • 【C#】获取不重复的编码(递增,非GUID)
  • 怎么理解API?
  • R-Zero:通过自博弈机制让大语言模型无需外部数据实现自我进化训练
  • LeetCode-238除自身以外数组的乘积
  • 大脑的藏宝图——神经科学如何为自然语言处理(NLP)的深度语义理解绘制新航线
  • PowerShell下vim编辑文件时产生的额外文件
  • 网站防爆破安全策略分析
  • KingBase数据库迁移利器:KDTS工具 MySQL数据迁移到KingbaseES实战
  • 学习设计模式《二十四》——访问者模式
  • 【数字投影】创新展厅视觉体验,3D Mapping投影全面解读
  • LaTeX论文转word插入mathtype公式
  • C/C++ 数据结构 —— 线索二叉树
  • 【C++】map 容器的使用
  • django配置多个app使用同一个static静态文件目录
  • Android Glide最佳实践:高效图片加载完全指南
  • 滥用Mybatis一级缓存引发OOM问题
  • 网络安全监控中心
  • 阿里云——计算服务深度解析与选型
  • ChatGPT 上线 “学习模式”:全版本开放,重构 AI 教育逻辑
  • 基于单片机步进电机控制电机正反转加减速系统Proteus仿真(含全部资料)
  • 北斗导航|接收机自主完好性监测算法综述
  • java数据类型获取长度方式总结
  • SpringBoot集成 DeepSeek 对话补全功能
  • Spark学习记录