粉丝522获赞1989
五分钟被八股卷进大厂,下面呢我们来讲解一下这道题叫 mvcc 解决的问题是什么?在讲明白这道题之前,同学们先要了解到底什么叫 mvcc, 他表示是说叫多版本并发控制啊,是经常用在数据库里面的一个技术,像麦克扣里面用的非常非常多 啊,当然你要想把这东西搞清楚的话,需要的知识储备是非常大的啊。我们先说他解决的问题到底是啥?我这边呢给大家做了一个文档的整理 啊,包含内容呢也比较多,是需要大家进行理解并且掌握的。然后谁如果需要当前的文档资料的话,扫描屏幕上右上角的二维码,找我的小助理进行领取。下面我们来看一下他 mvcc 到底解决什么问题。 先看一下在数据库进行并发操作的时候,主要有以下三种场景,分别是读读、写写 啊和读写三种情况啊。那么在每种情况下可能会产生一些数据安全问题。比如第一个,如果现在有一个县城 a, 有一个县城 b, 两个县城同时都去读同一份数据,注意啊,同一份数据, 这时候因为你没有对当前数据进行任何的更改操作,所以读到的数据值一定是一模一样的,此时他是不需不存在任何问题的,因此这种情况下面也不需要任何的并发控制。 但如果你现在是读写情况,现成 a 去读数据了,现成 b 去写数据了,那么这个时候问题就来了,我在进行读取数据的时候,我读到的数据到底是 b 现成或者 b 数 写之前的数据呢?还是写之后的数据呢?这样可能就会有一个疑问啊,而为了解决这件事情,或者说如果存在这样问题的话,可能会产生 什么叫脏毒换毒、不可重复毒等级系列问题。先把这个解决了,必须通过什么事物的隔离性来进行解决,好吧,这是第二种硬性场景,还有第三种场景叫什么叫写写?什么叫写写? 比如两个县城 a 也去写了,好吧, b 也去写了。在这个时候,假如说我 a 是把一改成了二, b 呢?是把一改成了三。如果我现在 b 和 a 都已经进行提交了,或者说他们提交的时机是有所不同的,如果我最终看到结果值是三, 那中间有没有可能发生一种情况,我二的更新给丢失了,比如说压根不存在二这个值的情况,这很明显也是不合适的。 好,那这种情况应该怎么办?是由一改成了二,由二改成了三,是不是这样一个情况?所以这个时候会引发一些更新丢失的问题?所以对于上面产生这些问题,好吧,我们必须要在 数据库层面把它解决掉,因为说白了吗?数据库是个啥来的?说了必须要保证数据的一致性,因此产生了 mvcc 这样一个技术,说了它是用来解决读写冲突的,无所并发控制的。 也就是说我们在进行实际的操作的时候,如果你加锁是可以解决问题的,但一旦加锁之后,你的效率会变得非常非常低 啊,那为了提高我们的效率,同时又解决了我们我们的问题怎么办?有了 mvcc 这项技术,说了他是为十五分配三项增长的时间,说吧,为每个修改保存一个历史版本数据,所以叫多版本啊, 比如说我之前形成的历史记录都会有对应的版本信息,我要把这些版本信息给记录下来,版本与事物时间戳进行相互的一个关联,读操作只读该事物开始前的数据库快照,所以 mcc 可以被 数据库解决。一、解决以下问题,好吧,什么问题?第一个叫在并发读,写数据库的时候可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高数据库的一个并发性能。 也就是说你现在不管有多少个事物再进行执行,你是读也好,你是写也好,他们相互之间并没有任何的影响。我读到的数据都是最终一致的,而到多数据都是一致啊,这第一个解决的问题。第二解决问题呢,叫解决了刚读、换读、不可重复读等事物隔离问题, 但是不能解决更新丢失问题。所以上面说了三种应用场景里面,它主要针对解决的是读写方面的问题,您注意啊,叫读写方面的问题啊,比如说有失误读,有失误写,我怎么解决是吧?把这段文字描述,希望大家能够背下来,当然面试中如果不问, 你可以按照我的描述去表示,不要只说读写。大家注意了,在回答面试问题的时候,一定要考察你自己的一个基础全面性,所以把这几种情况都提到,以及对应的一些解决方案,以及 mvcc 到底干了啥,把他给说清楚就够了。 好吧,这个东西就是我们这一道题的一个详细讲解,如果需要本集和资料的话,扫描屏幕上的右上角二维码,找我的小助理进行录取。这节课我们大概就讲这么多。
请说明 mvcc 原理详解 mvcc multi goverse longcom currency control 是一种数据库并发控制技术, 用于在多用户同时访问数据体时保证事物的隔离性和一致性。 mvcc 通过在数据库中保存多个版本的数据来实现并发控制。每个事物读取的数据是其启动时的一个一致版本,而不会受到其他事物的影响。 m v c e c e 的原理如下,版本号在 m v c e c e 中,每个数据行会保存多个版本, 每个版本都有一个唯一的时间戳或版本号。当一个事物开始时,会获得一个时间戳,该时间戳用于标记该事物的一致性。视图。写操作当一个事 物进行写操作时,数据库会生成该数句型的一个新版本,并将新版本的时间戳设为当前事物的时间戳,这样其他事物在之后的查询中将不会读取到。这个新版本保持了事物之间的隔离性。 读操作当一个事物进行读操作时,数据库会查找并返回该事物时间戳之前的最新版本数据, 这样事物读取的数据是在其启动时的一致性。视图不会受到其他事物正在进行的写操作的影响。并发控制 m v c e c 通过使用事物时间戳和 数据版本号来实现并发控制。当一个事物读取数据时,如果该数据的版本号大于该事物的 时间戳,则说明该数据已经被其他事物修改。该事物需要等待或选择其他的版本,这样可以避免脏毒不可中、复毒和患毒等并发问题。 mvcc 的优点是能够提供高并发性和较好的隔离性减少了所竞争, 从而提高了数据库的性能和吞吐量。但也有一些缺点,如增加了存储开销,因为需要保存多个版本的数据,同时 长失误可能导致版本链的增长。影响性能。 m v, c, e, c 被广泛应用于许多数据库管理系统中,如 post g, race q l 和 my s q l 的 e no d b 引擎等,以提供有效的并发控制和事物隔离。
京东真实面试题,买烧烤中 mvcc 解决了什么问题? mvcc 呢,是多版本并发控制解决的呢,其实就是数据库中的并发问题,而数据库中的并发又分为很多种,包含了咱们的独独操作,还有读写操作以及写写操作。 那么其中毒毒操作呢,是没有现成安全问题的,而毒血操作呢,会存在事物隔离性的问题,那可能会遇到咱们的脏毒,患毒,还有不可重复毒,而血血操作呢,可能会出现咱们更新丢失的问题。 而其中针对读写操作时啊,比如说县城 a 读取数据,县城 b 要写入数据,那么县城 a 读取的到底是县城 b 写入之前的还是写入之后的数据呢? mvcc 呢,就是解决这个问题的本质,其实就是为事物分配了一个单向增长的时间戳,将每个修改保存成一个版本, 而版本呢,与事物的时间戳进行关联之后,让独操作只读取该事物开启前的手机库的快照。 并且呢, mvcc 可以做到在读数据时不用去阻塞写操作,这样就提高了数据库的并发读写能力。还有呢,就是咱们的 macc 啊,它可以解决脏读换读以及不可重复读,但是它不能解决写写操作时的更新丢失问题,哈哈哈哈哈哈,哎呀,腰疼。
mc 口中的 r 十五隔离级别到底有没有解决患毒的问题?昨天在我的粉丝群里面就 mr 十五隔离级别到底有没有解决患毒问题发起了激烈的讨论,一部分人说有一部分人说没有。我先说结论, mr 十五隔离级别在特定的情况下会出现 患毒的问题。所谓患毒,表示在同一个事物中的两次相同条件的查询得到的数据条数不一样。那么在啊二的隔离级别下,具体什么情况会出现患毒呢?我们来看一下这样一个情况, 在事物一里面,通过啊不对的语句触发了当前读的情况下,就会导致在该事物中的前后两次查询的数据行数不一致,从而出现换读的现象。导致换读的根本原因是啊,不对的操作呢,会触发当前读操作绕过了快照读,从而导致 m v c c 机制在当 当前的场景下失效,最终读取到了十五二中已经提交的数据。为了避免在实际的开发中遇到这一类的问题,我们可以通过 for update 的语句去枷锁。 好了,今天的分享就到这里。另外呢,我收藏了好几本 mythical 底层工作原理的电子书,我自己看了以后呢,收获特别大,分享给关注了我的粉丝,仅限十份,大家可以在我的评论区置顶中去领取。
哈喽,各位小伙伴们大家好,我是一锅炖不下的北冥,那么今天呢,我们来深入的分析一下,在我们买 cco 当中,我们如何通过我们的 mvcc 机制来去保证我们的隔离性啊, 那么没有点过关注的小伙伴呢,也可以点波关注啊,那么我们接着往下去看,那么在上一讲呢,我们是跟大家介绍了有四个格力级别,对吧?那么第一个我们序列化,那么序列化呢,它本质上它是全程加锁的,它的一个性能呢是最差的,但是它保证的一致性能是最好的, 所以说在我们训练化呢,它是不需要用到我们 mvcc 的,而我们的未提交读呢,我们在去进行并发事务访问的时候,我们其实能够看见其他事务没有提交的修改,对吧?所以说也不存在什么格力性,那么只剩下我们可重复读和提交读,那么 mvcc 呢,其实也是在这两个级别上面工作啊, 那么在接下来我们深入的去分析我们 m v c c 机制的原理之前啊,我们先跟大家去铺垫两个知识,那么这两个知识呢,有助于后面大家能够更好地去理解啊。 首先要跟大家介绍的是我们的版本链啊,我们以往当我们去见一张表的时候,我们里面可能有些字段,对吧?那在这呢,我们有 id, 有 name 和余额,这个呢是我们能够看见的,但其实我们的表中呢,还有一些我们看不见的字段啊。 首先第一个是我们的事物 id, 当我们对某一条行记录去进行改动的时候,那么那个改动的事物呢?他的 id 会记在我们这个行里面啊, 这个呢就是我们的事务 id, 那么第二个我们的 ropent, 当我们去对某一行去进行改动的时候,我们是不是会通过我们的昂都日志去维护一些其他的版本,对吧?而 ropent 里面呢,他存的是他上 上一个版本的指针地址啊,那么他呢是直接链接到上一个版本的。跟大家举个例子吧,假设我们这边的 id 是一万零一啊,我们的另外是北冥,余额是九百块钱,那么当我们把余额从九百改成两千的时候, 那么我这条记录,那么它就叫做一条旧记录,对吧?那么我这条新记录呢?我的 report inter, 它会链接到我之前的那条旧记录里面啊,当我再次把余额从两千改成一千的时候,那么我的 report inter 呢,它也是会把地址链接到我的上一条, 那么他通过 report inter 把我们版本之间的修改呢,去连接成一个列表,那么我们把这个列表呢,就叫做我们的版本列啊,我们根据这个版本列,我们就能够去找到我们这一条数据的所有历史版本,那么 m v c c 呢,它其实就是通过这种方式去维护了多个版本的。 跟大家介绍完了我们的版本列之后,我们再来去看一下我们的 red view, 当我们去开启一个事物的时候,那么它同时呢,它会去生成一个 red view, 它里面呢是有几个比较重要的参数啊,我们来跟大家过一下。首先第一个我们的 id 列表,那么这个 id 列表呢,它里面存放的 是我们当前数据库里面我们所有的活跃事务 id 列表啊,而活跃事务呢,它指的是我们启动了,但是我们还没有提交的事务。那么第二个我们的最小事务 id, 它呢指的是我们在创建了我们 red view 的时候,我们当前数据库里面,我们活跃事务里面最小的一个事务 id 是多少?那么也就是我们这个列表里面最小的一个值啊。好。第三个我们的最大事务 id, 这个最大事务 id 呢,它并不是我们 id 列表里面最大的值了,那么是我们全局事务 id 里面最大的值。知道, 然后再加上一,那么再介绍最后一个我们的 great 事务 id, 也就是我创建了这个 red view 的事物,它呢就是我们当前的事务 id 啊。 我们介绍完了四个参数之后呢,我们再去看一下我们的 m v c c, 它是如何去结合我们 red view 去实现隔离性的啊?我们可以看到下面一张图,当我们事物启动的时候,它会去读取一个数据版本的数据 id 啊,那么它是有几种可能性的。 首先第一种,如果被访问的版本,那么他的事务 id 和我们 red view 里面创建事务 id 是相同的时候,那么也就意味着我当前事务我在访问我自己修改过的记录,对吧? 所以说这个版本呢,是我是可见的,如果我们是落在了这个绿色区域里面啊,那么他表示这个数据版本呢, 是已经提交的事物,或者是我们当前事物自己生成的,所以这个数据呢,也是可见的,如果落在的是红色区域呢,那么他表示我们这个版本他是由将来启动的事物生成的,所以对于我当前事物而言,我是看不见的,那么最后一个,如果说他落在了黄色区域里面, 那么它就有两种可能性的啊,如果我们的数据的是 y d, 在这个列表里面,那么它表示这个版本它是由还没有提到的事物生成的,对吧?所以说它是不可见的。如果这个版本数据的是 y d, 它不在这个 id 列表里面, 那么他表示我们这个版本他已经是已经提交的事物生成的,所以他是可见的。我们的 m v c c 呢,就是通过我们前面所介绍的版本链,再加上我们的 read view 来一起去控制了我们的并发事物访 问啊,那么对于前置知识呢,我们已经铺垫完了,那么接下来呢,我将带领大家通过实际具体的案例来去分析一下。 在这里我是准备了两个事务,一个事务 a, 一个事务 b, 那么事务 a 呢?主要是修改数据,那么事务 b 呢?是主要查数据啊,大家想一下,当我更新完事务 a 的时候,我们事务 b 他所查到的数据,那么到底是北冥二还是北冥呢?大家呢可以把这想法打在我们的评论区,那么接下来呢,我将带领大家去演示一下啊。 首先我在这呢已经提前准备好了两个 shift circle 啊,我们先来看一下它的一个隔离级别是什么, 我们可以看到它现在的级别是 r, 对吧?那么没有问题,首先我们开启个冰运数,然后呢把北名改成北面二,好可以看到呢,已经成功了,但是没有 commit, 我们来看一下北面 要查询啊,我们可以看到它当前的结果还是北冥,对不对?那么我来 commit 一下,我们再去看一下它的一个结果。 好,我们可以看到 commit 已经完成了,我们再去看一下。哎,我们这边看到我们查询出来的结果还是北冥,对不对?那可重复读呢?它就解决了我们不可重复读的问题啊。那么具体它是如何通过我们版本列和我们的 read view 来实现的呢?我们继续来分析我们的图啊, 我们刚刚的流程里面,我们是先去开启了我们示威的事物,然后呢将北明改成了北明二,对不对? 那么此时呢,他也会生成一个 red view 啊。首先第一个是我们当前事物的事务 id, 那么第二个是我们活跃事物的 id 列表啊,我呢只有一个事物,所以说他查出来呢,也只有我自己,对吧?那么最小事务 id 呢,也是我自己, 那么最大事务 id 呢,是我们全局最大 id 加一嘛?好,那么这个呢是没有问题的,那么当我去进行第一次查询的时候,我是不是也开启了一个事务,对吧?这样呢,我也会去创建一个 red view 的啊。首先第一个事务 id 呢是等于三,那么第二个 我们的活跃 id 输入列表里面呢,就有二和三的啊,而最小输入 id 呢是我们的二,那么最大输入 id 呢,那么就是我们的四,我们去按照我们前面和大家所说的那个规则,我们来去判断一下啊,那么当我们再去执行第二次 slack 语句查询的时候,那么他会发生什么事情呢? 我们来通过我们的上面的版本念跟大家去解释一下啊,首先第一步呢,他肯定是从页记录里面找吧,那么他的 name 呢是北冥二,他最重要匹配的是我们这个事务 id, 在我们查询事物的 read view 里面,我们的事务 id 列表是不是已经包含了二跟三,对不对? 那这边的数 id 是二呢?所以说明显他是不符合我们要求的,那他呢就会根据我们若 point 的规则去寻找我们下一条,当他定位到我们前一条数据的时候, 他依旧会去判断我们这个事务 id 啊,他会发现,哎,这边的事务 id 呢是我们的一,而我们的 red view 里面呢,我们最小事务 id 是不是我们的二,对吧?那么这个呢,就说明我们这个事务是不是已经提交过的, 当他确定这条数是已经提交过的,那么他呢就是可见的那可见的数据,那么他呢就会返回这一条啊,所以说我们最终看到的数据呢,是我们的北冥啊, 那么这个呢,就是我们可重复读的一个原理啊。那么接下来呢,我们再带大家去演示一下,在我们读以提交这个级别里面,他是怎么工作的啊?首先呢还是一样,我们呢也去看到下面这张图啊,在这呢也是两个事物,但是我把它的一个流程步骤呢也画出来了,首先我们的示威, 他会将内幕从北冥改成北冥二,然后呢我们开启了第二个事务,那么第二个事务里面呢,他执行的是一条查询语句,此时他是查不到示威更新结果的啊,那么继续往下走,就走到第三步,那么我们的示威呢,他就提交了事务, 那么第四步呢是我们再查询一遍,那么大家呢,也可以把这些想法打在评论区,那么看看最终出来的结果是北冥还是北冥二啊?那么接下来呢,我将带给大家去演示啊,那么同样的我们还是有两个事物啊,我们先来看一下它的一个隔离级别,我们现在呢是一个 r 的级别,对吧?我们先把它改成我们 r c, 好两个级别呢已经修改完成了,那么接下来呢,我将开启第一个事物,然后将北名改成北名二,我们可以看到第一个事物呢,已经执行成功了,我们再来看一下,我们开启第二个事物,然后我们执行查询,我们可以看 当前还是北冥,对不对?那么此时我将第一个事务去提交,那么我们再查询一遍, 我们可以看到我们能查询到北面二这个结果了,是吧?这个呢就说明他发生了不可重复读的一个现象啊。 那么具体我们 red view 和我们的版本念是如何工作在我们读以提交这个格力级别里面呢?我们接着去分析啊。首先是第一次,当我们去示威开启,然后执行更新语句,那么同时我们会创建一个 red view, 对吧?那么在 red view 里面, 假设我们这边事务 id 是一,那么我们的活跃事务列表里面也只有我自己,对不对?那么最小事务 id 和最大事务 id 呢?是一跟我们的二啊。然后我们来到了第二个事务,他是执行了一条查询语句,那么同样的他也会生成一份 read view 啊,我们可以看到我们的活跃事务列表里面,他发生了一点变化, 我们前面的示威呢,他正在执行,对吧?所以说我们前面一个是我和我自己,我们都是在这个里面的。然后第三步呢,我们回到了我们示威, 此时我去提交事务,那这个时候我们 read view 里面的内容呢?是不变的啊,它跟我们前面呢还是一样的,当我去事务 b 里面,我开始第二次查询的时候,我呢是会重新创建一个 ready view 啊,所以说我的事务 id 没变,但是它会将我们活跃事务列表去进一个更新啊,因为我们的事务 a 是不是已经提交了,对吧? 所以这个地方呢,只有事务二。那根据我们前面跟大家所介绍的规则,我们的事务一已经不在我们这个 id 列表里面了, 那么他是不是就满足了我们可见性的要求了,对吧?所以说我第二次查询的时候,我是能查看到北冥奥这个更新结果的,所以他就发生了不可重复读的现象啊,我们的可重复读隔离级别和读以提交隔离 级别,其中最大的一个差异就是在当我们去执行 slag 的语句的时候,他们去生成我们 red view 的规则是不一样的,我们可重复读呢,在一个事物里面,他只会生成一次,而我们的读以提交呢,他是每次去查询的时候, 它都会去生成一个新的 red vivo 啊,所以说它能更新我们活跃事物的一个 id 列表,正是因为这个原因,所以才造成了我们不可重复读的一个现象啊。那么在最后呢,我们再来跟大家去做一个总结啊, 事物呢,它是在我们 mcco 当中的引擎层实现的啊,我们常见的,像我们的英诺 db 呢,它是支持事物的,那么事物的四大特性呢?是我们原子一致隔离和持久,对吧?那么这一次和大家分享的呢,主要是我们的隔离性啊,当我们多个事物出现了并发执行的时候,他可能会引发赃读啊,不可重复读, 换读这些问题,对吧?那为了避免这些问题呢,蛇口呢就提出了四种隔离级别对不对?包括我们的毒液提交啊,毒液提交啊,可重复读和串形化,隔离级别越高,那么也意味着它的性能呢,是越差的啊。 如果说我们要解决脏读现象,那么我们就要将隔离级别最少要提升到我们已提交读里面,对不对?要解决不可重复读呢,我们最少要将级别提升到可重复读,那么要解决换读呢?我们不建议将级别提升到可序列化,它呢可能会导致我们数据库在并发的时候可能性能非常差啊。 而 innodb 引擎呢,它虽然默认知识的级别是可重复读,但是它通过了我们的行锁和间歇锁的组合,它呢去锁住了我们记录之间的间隙,包括我们记录本身啊,这样呢,它就能够防止我们其他事物在这个记录之间 插入新的记录啊,这样呢,它就避免了我们的患读现象。而对于我们刚刚所聊的已提交读和可重复读,那么这两个格力级别呢,它是通过我们版本念和 red view 来实现的,对吧?那么它们的区别最主要的是 在于创建 red view 的时机不同啊,那么刚刚呢,也跟大家介绍过了,对吧?那么关于今天的分享我们就聊到这里,如果大家觉得有些收获的话,那么可以给北门老师一个三点啊,有需要我们今天的笔记和我们 processo 里面的图的话,那么也可以评论区扣一领取啊!
什么是 m v c c? m v c c 是一种用于数据库系统的并发控制技术,它通过为每个事物创建独立的数据版本来实现事物隔离和一致性。 在 mvcc 中是否可以读取和修改数据而不会互相冲突并且读操作只能看到在起开始之前已经提交的版本。 当一个事物进行写操作时, mvcc 会创建新的数据版本,其他事物仍然可以读取以提交的旧版本。 mvcc 提高了变化性能,避免了一些所竞争和阻塞问题,但也有存储开销和版本念过长的限制。 注意,买锁口的印度 d b 存储引擎就是使用 m v c c 来支持事务操作的。
什么是脏读、患读、不可重复读?脏读、患读、不可重复读都是指事物并发过程中可能产生的问题。脏读表示的是在一个事物中读取到了另一个事物未提交的数据,由于另一个事物还未提交,因此数据是有可能被回滚的, 而一旦回滚就会导致当前事物读取到了错误的数据,从而导致数据的不一致。换读与不可从不读都是指在一个事物中读取到的另一个事物已经提交的数据,且多次读取的数据是不一致的。他们之间主要的区别是, 换读是一个事物中的多次相同的查询,查询到的数量不一致,通常是由新增或者删除这一类的操作而导致的。而不可重复读指的是一个事物中多次相同的查询,读取到的内容不一致。例如原先的名字是 a, 现在变成了 b, 通常呢,都是由修改操作导致的不可重复读。 那么在 mac 口中为我们提供了四个隔离级别,分别是读未提交、读已提交、可乘不读和串形化来解决这些问题。首先,读未提交是指一个事物中可以读取到另一个事物未提交的数据,可以理解为没有任何隔离性,因此也就什么问题都解决不了。 读已提交是指一个事物他只能读取其他事物已经提交的数据,此时可以为我们解决赃读的问题。但是换读和不可重复读依然是存在的, 我们可以利用可从不读来解决脏读和不可从不读问题,并且可从不读也可以为我们解决一定情况下的贩毒问题。 这个一定情况主要是指在可重复读中,买车口为我们实现了一个 m v c c 的机制,然后它可以帮我们解决快造读情况下的贩毒问题。但是在买车口中还存在另外一种读取数据的方式,叫做当前读,这样一种情况下,在 m v c c 里边它也是无 解决换读的。那么如果我们想要彻底解决张读换读不可重复读的问题,我们就得用到串形化这个合理级别。串形化是通过锁机制让我们的事物从并行执行变成串行的执行, 而由于事物的执行不存在并行执行了,因此这些并发问题也就不存在了。关注我,祝你升职加薪!