MySQL隔离级别 封锁协议 的简单讲解与实验

        之前上数据库课程的时候,这部分学的迷迷糊糊的,后来温习了一下,决定写一篇博客记录下来,同时尽量用最通俗易懂的方式讲出来。

        MySQL隔离级别有四个,分别是如下

                1. read uncommitted 读未提交。 大白话的举个例子,就是你和张三一起用客户端(就比如cmd打开的那个黑框)对同一个数据库中的同一张表进行操作,在张三开启他的事务之后,在他commit之前,你能看到张三对数据库做出的修改。换句话说,你能读到张三还未提交的操作,所以叫读未提交(我的个人理解)。

        看看实验: 设置隔离级别为读未提交,打开俩客户端,左右俩都begin开启事务 然后查询:

 现在让右边修改 id为1的地方的num值为10

现在让左边去查询一下,我们发现左边读到了右边还没提交的数据:

 这时如果右边回滚了,左边就读到了脏数据:

 

               

造成的问题: jerry的年龄是五岁,这时张三修改为6岁(张三还没提交)然后你读了一下,发现jerry年龄为6岁。这时张三那里发生一次回滚(rollback),jerry的年龄回滚为了5岁。你都到的就是脏数据了。      (解决方案在下一隔离级别)

                2.read commit 读已提交。 同样用大白话举例子,在这一隔离级别,同样是你和张三一起用客户端(是不是回想了我们之前说的黑框23333)。当你和张三同样对着一张表操作时,如果张三还没提交他的事务,那么你是看不到张三对表进行的修改的。只有当张三commit了以后,你才能看到张三对表进行的修改。换句话说,你能读到张三已经提交的操作,所以叫读已提交(我的个人理解)。 

                如何解决脏读: 在张三commit之前,你是看不到 张三的操作对表的造成的改变 的 。所以张三各种update rollback对你都没影响,只要他没提交。

                造成的问题: 如果张三修改表以后提交了(修改jerry的年龄为6),那你在他提交之前查询一次,发现读到的jerry年龄为5,当张三提交以后,你又查询一次,发现jerry的年龄为6.你的读操作不能重复进行了,这可咋办?  换句话说,你不可以重复读到相同的数据了。(官方一点,叫它不可重复读)。(解决方案在下一隔离级别)

实验:

如图:我们将隔离级别设置为读已提交,那么右边在自己的事务里面再怎么作,都不影响左边的查询:

 这里做一个小铺垫,我们在左边做了一次insert操作,但失败了,这是什么原因呢(之后解答)

回到问题,我们让右边提交,然后看看左边的查询有什么变化:

啊这,左边在自己的事务中,两次select查询居然查到了不同的数据! 左边不能重复读到相同的数据,真见鬼,为了解决这个问题,就需要下一隔离级别了。

                3.read repeatable 可重复读。我们继续大白话开始,这一隔离级别下,MySQL保证你在自己的事务开启到结束的时间内,一切操作都是可以重复的 。无论张三对表修改了什么,对你都是没有影响的。它保证了在上一个问题的场景里面,你在张三commit以后,查询到的jerry的年龄依然是5。 所以通俗的理解,就是在你的事务内,你读到的一切都是可重复进行的,不会因为别人对表的修改而改变。

                造成的问题: ok 张三放弃修改表数据了,但他往里面插入一条数据(姓名=tom ,年龄=3 为了方便 ,假设以姓名为主键)。这时候你突发奇想,发现表中没有tom的记录,就往表中insert(姓名=tom ,年龄=3)但这时候奇怪的事发生了,你发现这条数据无法插入表中! 这可奇怪了,这条数据查又查不到,想把这条数据插入表中,又成功不了,简直就像发生了幻觉一样令人迷惑。

例如:

 接着我们在右边插入一条数据:

 接着在左边去查询:

啊哈,只有三行,好哒,那我在左边插入 (4,4)试试 :

发现报错了,查又查不到,插入又插入不了,简直幻觉一样。

这就引出了 “幻读” 这个问题。解决方案在下一个隔离级别。

4.串行化

顾名思义,让这些并发的事务一个一个进行,在左边做了查询或修改以后,右边想要修改或插入数据,都得等到右边提交以后才行。这种隔离级别锁住了数据表,会导致一些效率问题(但它解决了幻读,因为当右边修改或插入以后,右边不能再进行修改和插入操作,这避免了幻读)。

实验如下: 左边比右边早开始

读的时候:

 这里读时加共享锁,所以右边也可以读取。

写的时候:

加排他锁,所以左边插入以后,右边不能读取或插入。

只有当左边提交以后,右边才能进行读操作:

我们基本做完了MySQL隔离级别的基础实验,如果这篇文章对你有帮助,那我很开心!! 

如果你有兴趣的话,可以看看接下来封锁协议的内容:

        一级封锁协议: 事务T在修改数据R前必须对它加X锁(排他锁),直到事务结束才释放。

还拿之前的例子举例,在读未提交级别:

 

 

可以看到左边对数据进行修改以后,在左边提交以前,右边无法获取X锁来进行修改,但可以正常读,插入数据。

        

        二级封锁协议:一级封锁的基础上添加事务T在读取数据R前必须对其加S锁,读后即可释放S锁。

 这里看一下,为什么左边update以后,右边还能select 出结果呢?这是因为select是不用加S锁的,要想对这一隔离级别做实验,我们要用 select    ---  lock in share mode;才行

果然,左边update后,右边得到如下结果

 当左边提交后,右边才能获取S锁查询。

        三级封锁协议: 在一级封锁协议上增加事务T在读取数据之前必须对其加S锁,直到事务结束才释放 。这里就不再演示了,有兴趣的小伙伴自己试验一下,2333333.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值