MySQL中的MVCC到底能不能解决幻读

MySQL 千万数据量深分页优化 在说MVCC之前呢?我们先需要对那些不太了解MySQL的兄弟们,先普及普及MySQL一些基本知识,具体MVCC内容往后看哦。 我们通过案例一步一步查看MySQL的MVCC到底是什么东西。 ** 在MySQL当中,只有使用了InnoDB存储引擎的数据库表才支持事务。 有了事务就可以用来保证数据的完整以及一致性,保证成批的SQL语句要么全部执行,要么全部不执行。 事务用来管理insert、update、delete语句。 1、四个特性(ACID): **原子性:**一个事务(transaction)中的 阅读详情

  • 在MySQL当中,只有使用了InnoDB存储引擎的数据库表才支持事务。

  • 有了事务就可以用来保证数据的完整以及一致性,保证成批的SQL语句要么全部执行,要么全部不执行。

  • 事务用来管理insert、update、delete语句。

1、四个特性(ACID):

  • **原子性:**一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • **一致性:**在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

  • **隔离性:**数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

  • **持久性:**事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。 复制代码

2、隔离级别

**

  • 读未提交(Read uncommitted),一个事务可以读取到其他事务中做出操作且还未提交的数据。会出现脏读,不可重复读,幻读现象。

  • 读已提交(Read committed),一个事务只能读取到其他事务中做出操作且已经做出提交的数据。会出现不可重复度,幻读现象。

  • 可重复读(Repeatable read),同一个事务内多次查询的数据保持一致。会出现幻读

  • 串行化(Serializable )是高的隔离级别,它求在选定对象上的读锁和写锁保持直到事务结束后才能释放,所以能防住上诉所有问题,但因为是串行化的,所以效率较低.

3、幻读、不可重复读、脏读

脏读:当一个事务读取到其他事务还未提交的数据,因为未提交的数据,不一定是最终有效的数据。所以我们称为读到脏数据了。也就是脏读。 不可重复读:一个事务A读取数据之后,另外一个事务B将此数据修改,此时事务A再次查询,发现数据不一样了。这就是不可重复读。也可以叫做幻读。 幻读:又叫"幻象读",是''不可重复读''的一种特殊场景:当事务1两次执行''SELECT ... WHERE''检索一定范围内数据的操作中间,事务2在这个表中创建了(如[[INSERT]])了一行新数据,这条新数据正好满足事务1的“WHERE”子句。

注:可能有点绕,一般情况下,“不可重复读”和“幻读”大致的意思相同。只不过不可重复度是在数据行上发生的,也就是发生了update操作,再去读取这条数据,出现不可重复读。而幻读是在数据表上发生的,也就是发生了insert与delete操作。再去读取这张表,出现数据条目或者行数(记录数)不一样。出现了幻觉一样。 **

4、MVCC(Multiversion Concurrency Control)多版本并发控制

数据库用于处理读写冲突的一种手段,目的在于提交数据库高并发场景下的吞吐性能。 版本链: 对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们 创建的表中有主键或者非NULL唯一键时都不会包含row_id列): trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。 roll_pointer:每次对某条记录进行改动时,这个隐藏列会存一个指针,可以通过这个指针找到该记 录修改前的信息。 比如说现在有这样一张表:t

ID

Name

1

小李

我们先假设新增这条记录的事务ID为80,那么此时此刻这条记录的版本链表如下图(因为是新增,所以这条版本链对应的roll_pointer是空):

​假如现在有两个事务ID分别为100、200,对这条记录进行update操作,具体走向流程如下:

贴心小课堂: 两个事务中不能交叉更新同一条记录哦?第一个事务更新了某条记录后,就会给这条记录加锁,另一个事务再次更新时就需要等待第一个事务提交了,把锁释放之后才可以继续更新。 复制代码

我们每一次对数据记录的改动,MySQL都会记录一条日志,我们把它称作undo日志,每一条undo日志对应着也都有一个roll_pointer属性(insert操作对应的undo日志没有该属性,因为该记录并没有更早的版本),可以将这些undo日志都连起来,串成一个链表,所以现在的情况就像下图一样:

​对这条记录每次更新后,都会将旧记录放入到undo日志中,就算是该记录的一个历史版本,随着更新次数的一次次增加,所有的版本都会被roll_pointer属性连接成一个链表,我们把这个链表称之为【版本链】,版本链的头节点就是当前记录最新的值。另外,每个版本中还包含生成该版本时对应的事务id,这个ID(事务ID)非常重要,后续事务的隔离级别实现原理都是围绕这个ID(事务ID)来的。

ReadView

** 对于使用【读未提交READ_UNCOMMITTED】这种隔离级别的事务来说,直接读取记录的最新版本就好了,对于使用【串行化SERIALIZABLE】隔离级别的事务来说,使用加锁的方式来访问记录。对于使用【读已提交READ COMMITTED】和【可重复读REPRATABLE_READ】隔离级别的事务来说,就需要用到我们上边所说的【版本链】了,核心的问题就是:我们需要判断版本链中的数据,哪个版本是当前事务可见的。所以设计MySQL官方提出了一个ReadView的概念,这个ReadView中主要包含当前MySQL中还有哪些活跃的读写事务,把它们的事务id放到一个列表中,我们把这个列表命名为为m_ids(一个数组)。这样在我们访问某一条记录时,只需要按照下边的步骤判断记录的某个版本是否可见(官方设计规则哦):

  • 如果被访问版本的trx_id属性值小于m_ids列表中最小的事务id,表明生成该版本的事务在生成ReadView前已经提交,所以该版本可以被当前事务访问。

  • 如果被访问版本的trx_id属性值大于m_ids列表中最大的事务id,表明生成该版本的事务在生成ReadView后才生成,所以该版本不可以被当前事务访问。

  • 如果被访问版本的trx_id属性值在m_ids列表中最大的事务id和最小事务id之间,那就需要判断一下trx_id属性值是不是在m_ids列表中,如果在,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问。

如果某个版本的数据对当前事务不可见的话,那就顺着版本链继续去找下一个版本的数据记录,依然按照我们上边所说的步骤判断数据是否可见,依此类推,一直到版本链中的最后一个版本数据,如果最后一个版本的数据我也不可见的话,那么也就意味着该条记录对该事务不可见,查询结果就不包含该记录。 在MySQL当中,READ COMMITTED(读已提交)和REPEATABLE READ(可重复读)隔离级别的的一个非常大的区别就是它们生成ReadView的时机不同,我们来具体举例看一下喽。 按照上面我们画的版本链,来具体分析一下,这个版本链是怎么一步步生成的,以及我们查询的时候,MySQL是怎么来通过版本链决定数据我们是否可读(可见)的。 --[1]--【R****EAD COMMITTED --- 每次读取数据前都生成一个ReadView】 假设说现在系统里有一个id为100的事务在执行:

# Transaction 100 BEGIN; UPDATE t SET name = '小B' WHERE id = 1; UPDATE t SET name = '小C' WHERE id = 1; # 注意哦:我们这个事务,我并没有提交。没有commit指令哦 复制代码
# Transaction 200 BEGIN; # 更新了一些别的表的记录 ... 复制代码
贴心小课堂:事务执行过程中,只有在第一次真正修改记录时(比如使用INSERT、DELETE、UPDATE语句),才会被分配一个单独的事务id,这个事务id是递增的。 复制代码

此刻,表t中id为1的记录得到的版本链表如下所示:

​千万注意,我上面事务100,还没提交哦,我可没有执行commit指令。 假设现在有一个使用READ COMMITTED(读已提交)隔离级别的事务开始执行:

# 使用READ COMMITTED隔离级别的事务(读已提交) BEGIN; # SELECT1:Transaction 100、200未提交 SELECT * FROM t WHERE id = 1; # 得到的列name的值为'小A' 复制代码

这个SELECT1的执行流程如下:

  • 在执行SELECT语句时会首先生成一个ReadView,ReadView的m_ids数组列表的内容就是[100,200]。

  • 然后从版本链中挑选可见的记录,从图中可以看出,最新版本的列name的内容是'小C',该版本的trx_id值为100,在m_ids列表内,所以不符合我们的可见性要求,根据roll_pointer跳到下一个版本。

  • 下一个版本的列name的内容是'小B',该版本的trx_id值也为100,也在m_ids列表内,所以也不符合要求,继续跳到下一个版本。

  • 下一个版本的列name的内容是'小A',该版本的trx_id值为80,小于m_ids列表中最小的事务id100,所以这个版本是符合要求的,最后返回给用户的版本就是这条列name为'小A'的记录。

之后,我们把事务id为100的这个事务提交一下,如下:

# Transaction 100 BEGIN; UPDATE t SET name = '小B' WHERE id = 1; UPDATE t SET name = '小C' WHERE id = 1; COMMIT; //提交了哦 复制代码

然后再到事务id为200的事务中更新一下表t中id为1的记录:

# Transaction 200 BEGIN; # 更新了一些别的表的记录 ... UPDATE t SET name = '小D' WHERE id = 1; UPDATE t SET name = '小F' WHERE id = 1; 复制代码

此刻,表t中id为1的记录的版本链就长这样:

​然后再到刚才使用READ COMMITTED隔离级别的事务中继续查找这个id为1的记录,如下:

# 使用READ COMMITTED隔离级别的事务 BEGIN; # SELECT1:Transaction 100、200均未提交的时候执行的查询 SELECT * FROM t WHERE id = 1; # 得到的列name的值为'小A' # SELECT2:Transaction 100提交,Transaction 200未提交的时候执行的查询 SELECT * FROM t WHERE id = 1; # 得到的列name的值为'小C' 复制代码

这个SELECT2的执行过程如下:

  • 在执行SELECT语句时会先生成一个ReadView,ReadView的m_ids列表的内容就是[200](事务id为100的那个事务已经提交了,所以生成快照时就没有它了)。

  • 然后从版本链中挑选可见的记录,从图中可以看出,最新版本的列name的内容是'小F',该版本的trx_id值为200,在m_ids列表内,所以不符合可见性要求,根据roll_pointer跳到下一个版本。

  • 下一个版本的列name的内容是'小D',该版本的trx_id值为200,也在m_ids列表内,所以也不符合要求,继续跳到下一个版本。

  • 下一个版本的列name的内容是'小C',该版本的trx_id值为100,比m_ids列表中最小的事务id200还要小,所以这个版本是符合要求的,最后返回给用户的版本就是这条列name为'小C'的记录。

以此类推,如果之后事务id为200的记录也提交了,再此在使用READ COMMITTED隔离级别的事务中查询表t中id值为1的记录时,得到的结果就是'小F'了,具体流程我们就不分析了。总结一下就是:使用READ COMMITTED隔离级别的事务在每次查询开始时都会生成一个独立的ReadView。 说完了隔离级别为【读已提交】不知道你理解了没有?如果不理解,烦请联系我,我们一起进行探讨。 接下来我们就来看一下当事务隔离级别为【可重复读】的时候,MVCC是如何控制数据可见性的。 --[2]--****【REPEATABLE READ ---在第一次读取数据时生成一个ReadView】 对于使用REPEATABLE READ隔离级别的事务来说,只会在第一次执行查询语句时生成一个ReadView,之后的查询就不会重复生成了。我们还是用例子看一下是什么效果。 比方说现在系统里有两个id分别为100、200的事务在执行:

# Transaction 100 BEGIN; UPDATE t SET name = '小B' WHERE id = 1; UPDATE t SET name = '小C' WHERE id = 1; 复制代码
# Transaction 200 BEGIN; # 更新了一些别的表的记录 ... 复制代码

此刻,表t中id为1的记录得到的版本链表如下所示:

假设现在有一个使用REPEATABLE READ隔离级别的事务开始执行:

# 使用REPEATABLE READ隔离级别的事务 BEGIN; # SELECT1:Transaction 100、200未提交 SELECT * FROM t WHERE id = 1; # 得到的列name的值为'小A' 复制代码

这个SELECT1的执行过程如下:

  • 在执行SELECT语句时会先生成一个ReadView,ReadView的m_ids列表的内容就是[100, 200]。

  • 然后从版本链中挑选可见的记录,从图中可以看出,最新版本的列name的内容是'小C',该版本的trx_id值为100,在m_ids列表内,所以不符合可见性要求,根据roll_pointer跳到下一个版本。

  • 下一个版本的列name的内容是'小B',该版本的trx_id值也为100,也在m_ids列表内,所以也不符合要求,继续跳到下一个版本。

  • 下一个版本的列name的内容是'小A',该版本的trx_id值为80,小于m_ids列表中最小的事务id100,所以这个版本是符合要求的,最后返回给用户的版本就是这条列name为'小A'的记录。

之后,我们把事务id为100的事务提交一下,就像这样:

# Transaction 100 BEGIN; UPDATE t SET name = '小B' WHERE id = 1; UPDATE t SET name = '小C' WHERE id = 1; COMMIT; 复制代码

然后再到事务id为200的事务中更新一下表t中id为1的记录:

# Transaction 200 BEGIN; # 更新了一些别的表的记录 ... UPDATE t SET name = '小D' WHERE id = 1; UPDATE t SET name = '小F' WHERE id = 1; 复制代码

此刻,表t中id为1的记录的版本链就长这样:

​然后再到刚才使用REPEATABLE READ隔离级别的事务中继续查找这个id为1的记录,如下:

# 使用REPEATABLE READ隔离级别的事务 BEGIN; # SELECT1:Transaction 100、200均未提交 SELECT * FROM t WHERE id = 1; # 得到的列name的值为'小A' # SELECT2:Transaction 100提交,Transaction 200未提交 SELECT * FROM t WHERE id = 1; # 得到的列name的值仍为'小A' 复制代码

这个SELECT2的执行过程如下:

  • 因为之前已经生成过ReadView了,所以此时直接复用之前的ReadView,之前的ReadView中的m_ids列表就是[100, 200]。

  • 然后从版本链中挑选可见的记录,从图中可以看出,最新版本的列name的内容是'小F',该版本的trx_id值为200,在m_ids列表内,所以不符合可见性要求,根据roll_pointer跳到下一个版本。

  • 下一个版本的列name的内容是'小D',该版本的trx_id值为200,也在m_ids列表内,所以也不符合要求,继续跳到下一个版本。

  • 下一个版本的列name的内容是'小C',该版本的trx_id值为100,而m_ids列表中是包含值为100的事务id的,所以该版本也不符合要求,同理下一个列name的内容是'小B'的版本也不符合要求。继续跳到下一个版本。

  • 下一个版本的列name的内容是'小A',该版本的trx_id值为80,80小于m_ids列表中最小的事务id100,所以这个版本是符合要求的,最后返回给用户的版本就是这条列name为'小A'的记录。

也就是说我们的两次SELECT查询得到的数据结果是一样(重复)的,列name值都是'小A',这就是【可重复读】的含义。如果我们之后再把事务id为200的记录也提交了,之后再到刚才使用REPEATABLE READ隔离级别的事务中继续查找这个id为1的记录,得到的结果还是'小A'。

MVCC总结

从上边的描述中我们可以看出来,所谓的MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTD、REPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程,这样就可以使不同事务的读-写、写-读操作并发执行,从而提升系统性能。READ COMMITTD、REPEATABLE READ这两个隔离级别的一个很大不同就是生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复这个ReadView就好了。

回到我们的标题: MySQL到底能不能解决幻读?或者说MySQL是如何解决幻读的? 现在你明白了吗? 欢迎一起讨论

MySQL可重复读隔离级别为何没有解决幻读(MVCC原理简介) MySQL可重复读隔离级别为何没有解决幻读(MVCC原理简介) 一.MCVV简介 二.可重复读隔离级别能解决幻读? 三.什么是当前读和快照读? 四.MVCC的实现原理 五.RC,RR级别下的InnoDB快照读有什么不同? 六.如何解决幻读 七.事务是么时候开始 阅读详情

相关推荐

从实验室到生活:构建一份全面的手机相机主观画质评测指南

本文详细介绍了如何从实验室数据转向实际体验,构建全面的手机相机主观画质评测指南。通过基础装备清单、室内外场景实战评测及数据之外的感知艺术,帮助用户发现手机相机在色彩还原、动态范围和夜景模式等方面的真实表现。特别关注主观体验与客观参数的差异,提供实用的评测技巧和报告撰写心法。

weixin_30940783的博客 308

MySQL(九):MVCC能否解决幻读问题

面试必问。聊聊MVCC到底能否解决幻读问题

Edwin_Hu的博客 1万+

4×V100部署Qwen3.8-Flash-Next:vLLM/GGUF实战

大模型本地部署的核心,是把参数量、量化精度、显存容量和推理框架放在同一张账本里算清楚。MoE 模型总参数量大但激活参数少,解码阶段更受显存带宽与 KV Cache 限制;通过 INT4/AWQ 或 GGUF 等 4-bit 量化可显著压缩权重占用,再结合 vLLM 张量并行、llama.cpp 分层切分提升多卡利用率。其技术价值在于让 V100 这类老架构 GPU 也能承载百亿级参数模型的私有化推理,并服务于 RAG 知识库、工作流 API、批量生成等场景。这次围绕 4×V100 32G 部署 Qwen3.

weixin_29061425的博客 349

MVCC能保证不产生幻读吗

MVCC多版本并发控制,在重复读的隔离级别下,用事务id为数据记录行标识了其版本,事务只能看到已经提交的、先于或者等于自己版本号的数据。但是仅仅依靠MVCC仍然无法完全避免幻读的情况发送。提示:以下是本篇文章正文内容,下面案例可供参考使用MVCC+间隙锁,可以解决幻读的问题。所以MVCC虽然是无锁的,却不能完全解决幻读,还是需要锁的参与。

Jiyip的博客 1731

Raid5损坏两块盘

  以下为浪潮Inspur NF5460M4型号服务器故障处理过程: 设备raid5组损坏两块硬,并raid组处理离线状态,情况如图:     由于硬盘数据比较重要,面对此情况不要慌我们尽量做到安全保守的保证数据尽可能完整,以下为处理方法,(遇raid5两块盘出现问题处理方法)   以下截图均为遇相同问题的解决图案,并非现场截图。 Ctrl+H 进WebBios界面,发现两...

chen_lipeng的博客 2万+

abb机器人指令手册_ABB机器人配置圆形输送链跟踪

更多内容请点击上方ABB机器人实战技巧关注也可点击公众号下方往期经典浏览更多内容转载请先后台留言,大家一起支持原创,推动机器人使用和发展本公众号对各类ABB机器人应用,仿真,毕业设计提供技术支持,详细后台留言本公众号诚挚希望与各机器人培训机构,机器人使用单元合作,提供技术支持,详细后台留言1. 通常的机器人输送链跟踪,均为直线输送链跟踪,例如下图2. 有些情况,输送链为圆形,例如...

weixin_39849894的博客 2044

mvcc 能不能解决幻读

快照读之间出现了当前读,可能产生幻读。因此mvcc不能完全解决幻读问题。需要加临键锁next-key。只有快照读,则不会产生幻读。锁住2条记录之间的间隙。

weixin_43803780的博客 583

FPGA音频处理入门:手把手教你用Verilog实现I2S接收模块(附完整代码)

本文详细介绍了如何使用Verilog在FPGA上实现I2S接收模块,涵盖I2S协议原理、Verilog架构设计、完整代码实现及优化技巧。通过实战案例,帮助开发者快速掌握数字音频处理技术,适用于嵌入式音频系统开发。

weixin_30335575的博客 418

mysql解决幻读_mysql中mvcc机制下RR级别不能解决幻读

四种隔离级别Serializable (串行化):可避免脏读、不可重复读、幻读的发生。Repeatable read (可重复读):可避免脏读、不可重复读的发生。Read committed (读已提交):可避免脏读的发生。Read uncommitted (读未提交):最低级别,任何情况都无法保证。事务并发的问题dirty reads (脏读)non-repeatable reads (不可重复...

weixin_39860755的博客 490

Android性能分析——hprof文件分析(一)

hprof  文件是 Java 堆转储文件(Heap Dump File)的标准格式,用于保存 Java 虚拟机(JVM)在某个时间点的内存快照。这种文件对于分析内存泄漏、内存使用情况和对象分配模式非常有用。

小旭的专栏 1880

python 实现一个完整的基于Python的多视角三维重建系统,包含特征提取与匹配、相机位姿估计、三维重建、优化和可视化等功能

本文介绍了一个基于Python的多视角三维重建系统的实现,涵盖了特征提取与匹配、相机位姿估计、三维重建、优化和可视化等功能。首先,系统通过安装必要的库(如OpenCV、NumPy等)并加载图像数据,初始化相机参数。接着,系统使用SIFT、SURF或ORB算法提取图像特征点,并通过FLANN或BF方法进行特征匹配,应用Lowe's ratio test筛选优质匹配。该系统为后续的相机位姿估计和三维重建奠定了基础,能够从多视角图像中恢复三维场景结构。

huanghm88的专栏 614

MySQL:图解MVCC到底能不能解决幻读问题?

图解MVCC到底能不能解决幻读问题

健身变秃,coding变强 1765

华为OD机考双机位C卷 - 两个字符串间的最短路径(Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 两个字符串间的最短路径(OD上机考试双机位C卷)。提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 835

mysql 幻读 mvcc_mysql中mvcc机制下RR级别不能解决幻读

四种隔离级别Serializable (串行化):可避免脏读、不可重复读、幻读的发生。Repeatable read (可重复读):可避免脏读、不可重复读的发生。Read committed (读已提交):可避免脏读的发生。Read uncommitted (读未提交):最低级别,任何情况都无法保证。事务并发的问题dirty reads (脏读)non-repeatable reads (不可重复...

weixin_39950772的博客 215

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

mysql session 查询_mysql中mvcc机制下RR级别不能解决幻读

四种隔离级别Serializable (串行化):可避免脏读、不可重复读、幻读的发生。Repeatable read (可重复读):可避免脏读、不可重复读的发生。Read committed (读已提交):可避免脏读的发生。Read uncommitted (读未提交):最低级别,任何情况都无法保证。事务并发的问题dirty reads (脏读)non-repeatable reads (不可重复...

weixin_28871475的博客 286

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ext grid隐藏的列不能修改_阿里二面:MySQL中的MVCC到底能不能解决幻读

微信搜一搜走进Java在说MVCC之前呢?我们先需要对那些不太了解MySQL的兄弟们,先普及普及MySQL一些基本知识,具体MVCC内容往后看哦。我们通过案例一步一步查看MySQL的MVCC到底是什么东西。在MySQL当中,只有使用了InnoDB存储引擎的数据库表才支持事务。有了事务就可以用来保证数据的完整以及一致性,保证成批的SQL语句要么全部执行,要么全部不执行。事务用来管理inse...

weixin_39639919的博客 87

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

MySQL中的幻读问题

当事务在范围查询中遇到其他事务插入或修改的符合条件的新数据时,可能会导致前后查询结果不一致,这种现象称为幻读。锁定范围而非具体记录,阻止其他事务在锁定范围内插入新数据,从而在可重复读(REPEATABLE READ)隔离级别下避免幻读。在可重复读隔离级别下,虽然快照读和间隙锁大大减少了幻读的发生,但仍然存在无法完全覆盖的场景,尤其是复杂的范围查询。使用快照读时,即使其他事务对数据进行了插入或修改,当前事务依然能看到事务开始时的数据状态。通过更严格的锁机制,彻底避免了所有类型的幻读问题,但以性能开销为代价。

m0_53926113的博客 1780

MySQL 可重复读隔离级别,完全解决幻读了吗?

事务隔离级别是数据库用来控制多个并发事务之间如何交互的机制。不同的隔离级别提供了不同程度的保护,以防止并发事务之间的相互干扰。读未提交(Read Uncommitted):最低的隔离级别,允许一个事务读取其他事务尚未提交的数据,可能会导致脏读、不可重复读和幻读。读已提交(Read Committed):只允许读取已经提交的数据,可以防止脏读,但仍然可能发生不可重复读和幻读。可重复读(Repeatable Read)

Amsssssssssss的博客 1473

RR不能解决幻读的原因

当执行 SELECT ... FR UPDATE、UPDATE、DELETE 等操作时,InnDB 会自动为影响的数据加上 Next-Key Lck,从而防止其他事务插入或删除数据,导致幻读。对于select * frm table where id = 10 fr update, 会锁住id=10的索引和间隙, 防止其他事务修改id=10,或者插入id = 10.x 的数据。当一个事务在读取数据时,MVCC不会记录新插入的数据,当再次读取的时候,新插入的数据就会造成幻读。

Gaorui678的博客 486

MySql事务的隔离级别和MVCC?

事务是是一组原子性的操作,或者说是一个独立的工作单元‌。事务内的操作要么全部执行成功,要么全部执行失败,不能只执行其中的一部分。事务的隔离级别是为了解决多个事务同时运行并访问同一数据时可能出现的并发问题,而设定的事务之间的隔离程度。有一下四个隔离级别:Read Uncommitted(读未提交):这是最低的隔离级别,它允许脏读,也就是可以读取到其他事务未提交的修改。

weixin_45367411的博客 1893

MVCC【重点】

参考链接1、数据库为什么要有事务?【为了保证数据最终的一致性。2、事务包括哪几个特性?【原子性、隔离性、一致性、持久性。3、事务的并发引起了哪些问题?事务并发会引起【脏读、重复读、幻读】问题。4、怎么解决事务并发出现的问题?进行事务隔离,针对不同的并发问题,设置不同的的事务隔离级别【读未提交,读提交,重复读,序列化】。5、数据库通过什么方式保证了事务的隔离性?通过【加锁】来实现事务的隔离性。6、频繁的加锁会带来什么问题?

qq_45927881的博客 1654

MVCC下的RR和RC级别的区别和实现

最近在学习MVCC,在学习过程中,很疑惑RC(读已提交)和RR(可重复度)级别都用到了MVCC来进行不加锁的读,但是为什么RR级别可以解决幻读,对于RC级别不行? MVCC即多版本并发控制,能够保证多个读请求之间不会进行阻塞,根据事物隔离级别和事物id来确定当前事物能够查询到的数据的版本。对于每行记录来说,可能会存在多个版本,而这些版本会使用使用链表进行关联起来,从而控制一个事务能够查询到的数据的版本。 首先需要明白事务的隔离级别和MVCC有密切的关系,你能深入事务的隔离级...

qq_35634181的博客 1万+

介绍一下 MVCC

介绍一下 MVCC

wy990880的博客 1054
上一篇: Java常见问题之HashMap扩容、树化、死链
下一篇: Java 提供了哪些 IO 方式? NIO 如何实现多路复用?
Java_LingFeng
博客等级 码龄4年 505粉丝 259原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值