首页 > 其他分享 >一次性掌握innodb引擎如何解决幻读和不可重复读

一次性掌握innodb引擎如何解决幻读和不可重复读

时间:2023-06-19 09:23:33浏览次数:43  
标签:隔离 RR 幻读 版本号 trx 引擎 innodb 级别 id

了解mysql的都知道,在mysql的RR(可重复)隔离级别下解决了幻读和不可重复。你知道RR下是怎么解决的吗,很多人会回答是通过MVCC和next-key解决的,具体是怎么解决的,今天来重点分析下。

mysql的隔离级别都不陌生了,简单回顾下四种隔离级别:RU(读未提交)、RC(读已提交)、RR(可重复读)【默认隔离级别】、Serializable(可串行化)。四种隔离级别控制力度有浅到深。日常的系统中常使用RC、RR两种,最常用的是RR。

一、认识两种读

说起mysql,很多人会给你说有两种读:快照读和当前读。我更喜欢在他们前面加个修饰那就是在RC、RR隔离级别下才有快照读和当前读。为什么这样说,这是因为只有在这两种隔离级别下才会有两种读。其他则是只有一种读那就是当前读。

在RU隔离级别下,不需要进行控制,可以读到其他事务未提交的事务,那肯定是当前读了。

在Serializable隔离级别下,所有的sql都会加锁,查询类型的sql加S(共享)锁、更新类型的sql加X(排它)锁。自然也都是当前读。

在RC、RR隔离级别下分别要解决脏读、幻读和不可重复读,所以才有了快照读和当前读。

 

关于对快照读和当前读的理解,从字面意思上理解即可,快照读也就是会读取一个快照版本,或者说历史版本;当前读就是读取当前的最新的数据。

在RU、Serializable隔离级别下,普通的select语句都是当前读;在RC、RR隔离级别下普通的select语句都是快照读。由于平时使用RR隔离级别多,所以,默认select语句都是快照读。

不论在哪种隔离级别下更新操作(insert/update/delete)都是当前读,当前读是要加锁的;下面的sql也是当前读,

select ... for update;  加X(排它)锁

select ... in share mode; 加S(共享)锁

二、认识MVCC

MVCC(Multi-Version Concurrency Control)翻译过来是多版本并发控制,存在于RC、RR隔离级别下,用于快照读。是这样来实现的,存储引擎全局维护了一个系统版本号,每开启一个新的事务,这个系统版本号就会递增。事务开始时刻的系统版本号,会作为这个事务本身的版本号。在每行记录中,存储引擎又在每行的后面保存两个隐藏的列,分别保存这一行的开始版本号(trx_id)和过期版本号(roll_pointer)。版本号就是事务ID。

看下各种更新语句版本号的情况,

insert,存储引擎为新插入的每一行保存当前的系统版本号作为这一行的开始版本号。

update,存储引擎会新插入一行记录,当前的系统版本号是新记录行的开始版本号;同时会将当前行的过期版本号设为原来行的系统版本号;

delete,存储引擎将删除的记录行的过期版本号设置为当前的系统版本号。

还要了解另外一个概念,readview

readview用来判断版本链中哪个版本对当前事务是可见的,包含4个重要属性:
  m_ids:生成ReadView时,当前系统活跃的事务id列表;
  min_trx_id:列表中的最小事务id;
  max_trx_id:列表中最大事务id;
  creator_trx_id:生成该ReadView自身事务的id。

注意:如果一个事务只读,则creator_trx_id默认为0,只有当事务发生INSERT和UPDATE、DELETE操作时才会分配该事务id。creator_trx_id是为了判断这条undo log是否是自己生成的。

如何判断数据的可见性,

  1. 从记录的最新版本开始迭代依次取隐藏列trx_id和ReadView的m_ids、min_trx_id、max_trx_id比较。
  2. 如果trx_id等于creator_trx_id表示该版本是自己更新的,版本可见;
  3. 如果trx_id在m_ids列表中,则该版本不符合可见性要求;
  4. 如果版本trx_id小于min_trx_id,表示事务在创建ReadView时已经提交,版本可见;
  5. 如果版本trx_id大于max_trx_id表示,该事务是在ReadView生成之后创建和提交的,不符合可见性要求;

简单点来说,MVCC就是基于记录的事务id做控制,一条记录会有多个事务id,代表多个事务id的记录会存储在undo log中。

三、解决幻读和不可重复读

3.1、select

在RC隔离级别下,解决了脏读的情况,是怎么解决的呐,当然是通过MVCC,因为MVCC是基于事务ID,也就是trx_id,所以在select的时候读取的一定是commit之后的数据,不提交没有trx_id哦,注意在RC隔离级别下是每次select都会产生一个独立的readview,所以幻读和不可重复读是无法解决的。

在RR隔离级别下,肯定脏读是不存在的。同时解决了幻读和不可重复读,也是通过MVCC,只不过这里生成readview的时机和RC隔离级别下不一样,在RR隔离级别下readview是在事务的第一个select的时候生成的,以后的select会使用第一个select的readview,这样就可以解决了幻读和不可重复读。

3.2、update/insert/delete

update/insert/delete语句都是当前读,为什么在更新语句中会有读,这是因为在执行更新操作的时候肯定要先读出来,再进行更新,这里的读便是当前读,只不过这里的当前读在RR隔离级别下是通过加next-key解决的,所以在RR隔离级别下可以解决幻读和不可重复读。

总结

本文重点分享了mysql的innodb引擎如何解决幻读和不可重复读。重点关注两点,

1、MVCC,快照读的时候使用MVCC;

2、next-key,当前读加next-key;

推荐阅读

花了一周时间,总算把mysql的加锁搞清楚了,再也不怕间隙锁和next-key了

java面试一日一题:讲下mysql中的undolog

 

标签:隔离,RR,幻读,版本号,trx,引擎,innodb,级别,id
From: https://www.cnblogs.com/teach/p/17486668.html

相关文章

  • 一文搞懂V8引擎的垃圾回收机制
    前言我们平时在写代码的过程中,好像很少需要自己手动进行垃圾回收,那么V8是如何来减少内存占用,从而避免内存溢出而导致程序崩溃的情况的。为了更高效地回收垃圾,V8引入了两个垃圾回收器,它们分别针对不同场景进行工作。垃圾从何而来我们先来搞清楚这些‘垃圾’是怎么产生的不管使用哪一......
  • MegEngine 动态执行引擎 Imperative Runtime 架构解析
    在之前的文章中我们介绍过 MegEngine 的 ImperativeRuntime 以及它与 MegBrain、MegDNN 的关系,这篇文章中我们将介绍 Imperative 中包含的常用组件。在 MegEngine 中,从用户在 python 层编写代码到在 interpreter 层发生计算经过了下面的流程:用户在 python 层......
  • 一文读懂火山引擎A/B测试的实验类型(1)——编程实验
    一.概述编程实验:指的是通过代码编程进行AB实验,广泛使用于前端优化、策略优化和后端算法优化多种实验场景,包含客户端和服务端实验。前置条件:接入客户端SDK或者服务端SDK,详见:应用接入二.应用场景如何选择实验类型?适用场景是什么?服务端实验:指通过服务端获取实验分组信息并......
  • 一文读懂火山引擎A/B测试的实验类型(1)——编程实验
    一.概述编程实验:指的是通过代码编程进行AB实验,广泛使用于前端优化、策略优化和后端算法优化多种实验场景,包含客户端和服务端实验。前置条件:接入客户端SDK或者服务端SDK,详见:应用接入二.应用场景如何选择实验类型?适用场景是什么?服务端实验:指通过服务端获取实验分组信息并控制配置......
  • 搜索引擎1-认识全文检索
    1.关于全文检索需要懂的什么叫做全文检索呢?这要从我们生活中的数据说起。我们生活中的数据总体分为两种:结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。非结构化数据(也叫全文数据):指不定长或无固定格式的数据,如邮件,word文档等。半结构化数据:如XML,HTML等,当根据需要可按......
  • 最全的iOS物理引擎demo
    概述最全的iOS物理引擎demo,实现重力、碰撞、推力、摆动、碰撞+重力、重力弹跳、仿摩拜单车贴纸效果、防iMessage滚动效果、防百度外卖首页重力感应等效果!详细一、准备工作1、需要Xcode8+iOS8的运行环境2、本例子实现重力、碰撞、推力、摆动、碰撞+重力、重力弹跳、仿......
  • 百度双塔召回引擎MOBIUS
    1.概述对于一个搜索或者推荐系统来说,分阶段的设计都是当下的一个标配,主要是为了平衡效率和效果,在百度的广告系统中,也是分成了如下的三层结构:最上层的Matching阶段负责从全库中找到与query相关的候选集,接下来的两个阶段则是根据不同的指标对候选集进行筛选,通常称中间的筛选过程为粗......
  • InnoDB的并发线程配置
    InnoDB使用操作系统线程来处理用户事务的请求。(事务在提交或回滚之前可能会向InnoDB发出许多请求)在具有多核处理器的现代操作系统和服务器上,上下文切换非常高效,大多数工作负载都可以很好地运行,而不会限制并发线程的数量。在有助于最小化线程之间的上下文切换的情况下,InnoDB可以......
  • 火山引擎数智平台VeDI荣获虎啸奖“年度最佳智能营销平台”奖项
    近日,由中国商务协会数字营销专业委员会指导的第十四届虎啸奖正式公布获奖名单,火山引擎数智平台VeDI荣获技术平台/产品类奖项。作为国内品牌营销领域兼具权威性、前瞻性以及创新性的赛事活动,第十四届虎啸奖累计收到来自品牌主、代理机构、媒体平台、技术公司等近850家参赛公司的积极......
  • 火山引擎数智平台VeDI荣获虎啸奖“年度最佳智能营销平台”奖项
    近日,由中国商务协会数字营销专业委员会指导的第十四届虎啸奖正式公布获奖名单,火山引擎数智平台VeDI荣获技术平台/产品类奖项。 作为国内品牌营销领域兼具权威性、前瞻性以及创新性的赛事活动,第十四届虎啸奖累计收到来自品牌主、代理机构、媒体平台、技术公司等近850家参赛公司......