男女啪啪抽搐高潮动态图 幻读为什么会被 MySQL 单独拎出来科罚?


发布日期:2022-05-11 10:28    点击次数:63

男女啪啪抽搐高潮动态图

本文转载自微信公众号「飞天小牛肉」,作家飞天小牛肉 。转载本文请关系飞天小牛肉公众号。

所谓幻读,即一个事务在前后两次查询归并个限制的时间,后一次查询看到了前一次查询莫得看到的行,这个回复猜测大伙儿照旧背烂了,然则它具体有什么后果呢?为什么会被 MySQL 单独拎出来科罚呢?MySQL 又是如何科罚的呢?

刻下读和快照读

在了解幻读以及 MySQL 是如何科罚幻读这个问题前,咱们需要清醒,什么是刻下读、什么是快照读。

快照读:读取快照中的数据,不需要进行加锁。看到快照这两个字,列位确定随机就意想 MVCC 了,是这么,MVCC 作用于读取已提交和可类似读(默许)这两个阻拦级别,这俩阻拦级别下的平凡 select 操作即是快照读 刻下读:读取的是最新版块的数据, 而况对读取的记载加锁, 结巴其他事务同期更动沟通记载,幸免出现安全问题。

除了读取已提交和可类似读这俩阻拦级别下的平凡 select 操作,其余操作都是刻下读:

select...lock 男女啪啪抽搐高潮动态图in share mode (分享读锁) select...for update update, delete, insert 

举个例子,来直觉感受下快照读和刻下读,以可类似读阻拦级别为例,假定咱们面前有一张 user 表,有如下的数据:

开启两个事务:

事务 1 先来个快照读望望:

没罪戾,很遍及。

事务 2 修改 age = 99,然后提交:

你猜,这时间,事务 1 快照读出来的数据应该是若干?

是的,仍然是旧数据:

那事务 1 “刻下读” 出来的数据确定是最新的了:男女啪啪抽搐高潮动态图

幻读到底有什么问题

所谓幻读,即一个事务在前后两次查询归并个限制的时间,后一次查询看到了前一次查询莫得看到的行。

在可类似读阻拦级别下,平凡的查询是快照读,刻下事务是不会看到别的事务插入的数据的。因此,幻读问题在 “刻下读” 下才会出现。

也有好多的著作说用 MVCC 来科罚 "快照读" 下的幻读问题,我认为没必要纠结吧,以至可能口试官更可能振作听到 MVCC 的旨趣。

不外,话说牵记,莫得 MVCC 机制,哪来快照读这个东西?

那么,幻读到底有什么问题?它具体有什么后果呢?

未几谎话,径直上例子:

咱们有一张表 user(id, username, age),照旧有两条数据 (1, "Jack", 20), (2, "Tom", 18)

有如下三个事务:

家喻户晓,select for update 语句会加行锁,假定,提防这里是假定奥!!!假定事务 1 的 select * from user where name = 'Jack' for update 只在 id = 1 的这一转上加行锁

不错看到,事务 1 奉行了三次查询,都是要查出 name = "Jack" 的记载行。提防咱们假定这里只在 name = 'Jack' 行上加行锁

第一次查询只复返了 id = 1 这一转 在第二次查询之前,事务 2 把 id = 2 这一转的 name 值改成了 "Jack",因此事务 1 第二次查询的独揽是 id = 1 和 id = 2 这两行 在第三次查询之前,事务 3 插入了一个 name = "Jack" 的新数据,因此事务 1 第三次查询的独揽是 id = 1、id = 2 以及 id = 3 这三行

昭彰,第三次查询读到的 id = 3 这一转的表象,即是幻读

但其实从逻辑上来说,这似乎是莫得问题的。

因为这三个查询都是加了 for update,都是刻下读。而刻下读的轨则,即是要能读到通盘照旧提交的记载的最新值,是以第二次查询和第三次查询即是应该看到事务 2 和事务 3 的操坐法果。

那么,幻读到底有啥问题?

率先是语义上的。事务 1 在第一次查询的时间就声明了,我要把通盘 name = "Jack" 的行锁住男女啪啪抽搐高潮动态图,间隔别的事务对 name = "Jack" 的行进行读写操作。

然则,本色上,这个语义被纰漏了,举个例子,我再旧事务 2 里加一条 SQL 语句(黄色框框):

事务 2 的第二条语句的情理是 "把 id = 2 这一转的 age 值改成了 40",这行的 name 值是 "Jack"。

而在这之前,事务 1 仅仅给 id = 5 的这一转加了行锁,并莫得给 id = 2 这行加锁。是以,事务 2 是不错奉行这条 update 语句的。

据介绍,Python 语言广泛应用于科学计算等,开发者常常通过代码复用提高开发效率。但 Python 程序运行环境复杂,依赖于 Python 包、系统库和特定版本的 Python 解释器。缺少程序依赖或者依赖版本不兼容,会导致程序构建失败和运行错误。

自监督预训练在自然语言处理方面取得了惊人的成功,其基本思路中包含着掩码预测任务。前段时间,何恺明一作的论文《Masked Autoencoders Are Scalable Vision Learners》提出了一种简单实用的自监督学习方案 MAE,将 NLP 领域的掩码预测(mask-and-predict)方法用在了视觉问题上。现在来自 Facebook AI 研究院(FAIR)的研究团队又提出了一种自监督视觉预训练新方法 MaskFeat。

前不久,百度产业级知识增强大模型 “文心” 全景图亮相,近日,其中的跨模态生成模型 ERNIE-ViLG 在百度文心官网开放体验入口,并放出了论文:

最新的指控在联邦大陪审团返回的替代起诉书中提出,增加了先前对妨碍司法和“重罪误判”的指控。

这么,事务 2 先将 id = 2 的 name 改为 Jack,然后再将 age 改为 40,纰漏了事务 1 对要把通盘 "name = Jack 的行锁住" 的声明

其次,最蹙迫的是,是数据一致性的问题。

家喻户晓,加锁是为了保证数据的一致性,这个一致性,不仅包括数据的一致性,还包括数据和日记的一致性,举个例子:

给事务 1 再加上一条 SQL 语句(黄色框框)

我在上图中圈出了四个技巧, T1 T2 T3 和 T4,咱们来分析下经过这四个技巧的数据库情状:

经过 T1 技巧,id = 1 这一转形成 (1, Tom, 20),提防这是在 T4 才讲求提交的 经过 T2 技巧,id = 2 这一转形成 (2, Jack, 40) 经过 T3 技巧,表内部多了一转 (3, Jack, 30)

再来望望这时间 binlog 日记内部的内容,binlog 即是记载下咱们做了哪些操作嘛:

T2 技巧,事务 2 提交,写入了 2 条 update 语句;

update user set name = "Jack" where id = 2 update user set age = "40" where id = 2 /*(2, Jack, 40)*/ 

T3 技巧,久久丫精品国产亚洲av事务 3 提交男女啪啪抽搐高潮动态图,写入了 1 条语句; 

insert into user values(3, "Jack", 30) /*(3, Jack, 30)*/ 

T4 技巧,事务 1 提交,binlog 中写入了 update user set name = "Tom" where name = "Jack" 这条语句

update user set name = "Tom" where name = "Jack" 

即是说,把通盘 name = Jack 的行,都给我改成 name = "Tom"

这么,问题就来喽,binlog 一般都是用于备库同步主库的对吧,这个 binlog 一奉行,那岂不是原先 (2, Jack, 40) 和 (3, Jack, 30) 这两行的 name 透顶形成了 Tom。

也即是说,id = 2 和 id = 3 这两行,发生了数据不一致。

提防!这个数据不一致到底是怎样发生的?是假定事务 1 的 select * from user where name = 'Jack' for update 只在 id = 1 的这一转上加行锁导致的。

很昭彰,分析到这里,咱们照旧领悟,只锁这一转是分辨理的。那好办,让 select for update 把通盘扫描到的行都给锁住不就行了?

这么,事务 2 在 T2 技巧就会被结巴住,直到事务 1 在 T4 技巧 commit 开释锁。

由于 session A 把通盘的行都加了写锁,是以 session B 在奉行第一个 update 语句的时间就被锁住了。需要比及 T6 技巧 session A 提交以后,session B 能力继续奉行。

But,这么看似没问题,是否的确没问题呢?

来看 binlog,奉行序列是这么的:

事务 3: insert into user values(3, "Jack", 30) /*(3, Jack, 30)*/  事务 1: update user set name = "Tom" where name = "Jack"  事务 2: update user set name = "Jack" where id = 2 update user set age = "40" where id = 2 /*(2, Jack, 40)*/ 

不错看到,事务 2 的问题确乎是科罚了,Jack 保住了,仍然是 (2, Jack, 40)

然则!!!提防事务 3,在数据库内部的独揽是 (3, "Jack", 30),而把柄 binlog 的奉行独揽是 (3, Tom, 30),也即是说幻读的问题照旧莫得科罚。

那为什么咱们照旧把通盘巧合扫描到的记载都加上了锁,照旧抵制不了 id = 3 这一转的插入和更新呢?

很简便。在咱们给通盘行加锁的时间,id = 3 这一转还不存在,数据库扫描不到,也就固然加不上锁了。

这亦然为什么幻读问题会被单独拿出来科罚的原因,即使咱们把通盘的的记载都加上锁,照旧抵制不了新插入的记载。

MySQL 如何科罚幻读

面前你清醒了,产生幻读的原因是,行锁只可锁住行,然则新插入记载这个行动,操作的是锁住的行之间的 “谬误”。因此,为了科罚幻读问题,InnoDB 只好引入新的锁,也即是谬误锁 (Gap Lock)。

这么,当你奉行 select * from user where name = 'Jack' for update 的时间,就不啻是给数据库中已有的 n 个记载加上了行锁,还同期加了 n + 1 个谬误锁(这两个合起来也成为 Next-Key Lock 临键锁)。也即是说,在数据库一转行扫描的经过中,不仅扫描到的行加上了行锁,还给行双方的闲隙也加上了锁。这么就确保了无法再插入新的记载。

这里多提一嘴,update、delete 语句用不上索引是很恐怖的。

对非索引字段进行 select .. for update、update 或者 delete 操作,由于莫得索引,走全表查询,就会对通盘行记载 以及 通盘间隔 都进行上锁。而关于索引字段进行上述操作,唯有索引字段自身和隔邻的间隔会被加锁。

总结下 MySQL 科罚幻读的妙技:

阻拦级别:可类似读

快照读 MVCC + 刻下读 Next-Lock Key(只在可类似读阻拦级别下奏效)

阻拦级别:SERIALIZABLE

在这个阻拦级别下,事务在读操作时,先加表级别的分享锁,直到事务完了才开释;事务在写操作时,先加表级别的排它锁,直到事务完了才开释。也即是说,串行化锁定了整张表,幻读不存在的

终末放上这道题的背诵版:

口试官:幻读有什么问题,MySQL 是如何科罚幻读的

小牛肉:幻读即是一个事务在前后两次查询归并个限制的时间,后一次查询看到了前一次查询莫得看到的行。

幻读的后果即是数据库中的数据和 binlog 的奉行独揽会不一致,其原因就在于,咱们无法抵制新插入的数据。即是说,咱们在给扫描到的行加锁的时间,你等会要插入的行还不存在,也就没法对他进行加锁,那么这个新插入的数据,可能在主库中是这个神志,从库奉行完 binlog 后其实是会被修改的。

这也即是为啥幻读会被单独拎出来科罚的原因了。

幻读问题在 "刻下读" 下才会出现。

所谓刻下读即是,读取的是最新版块的数据, 而况对读取的记载加锁, 结巴其他事务同期更动沟通记载,幸免出现安全问题。

与之对应的,快照读,读取的是快照中的数据,不需要进行加锁。读取已提交和可类似读这俩阻拦级别下的平凡 select 操作即是快照读。其实即是 MVCC 机制,或者说,在快照读下,接管 MVCC 机制科罚幻读。

然后,关于刻下读这种情况,前边咱们说,由于无法抵制新插入的数据,是以无法科罚幻读问题,是以,咱们琢磨,不仅对扫描到的行进行加锁,还对行之间的谬误进行加锁,这么就能根绝新数据的插入和更新。这个其实即是记载锁 Record Lock 和谬误锁 Gap Lock,也被称为临键锁 Next-Lock Key。

 额临键锁只在可类似读也即是 InnoDB 的默许阻拦级别下奏效。也不错接管更高的可串行化阻拦级别,通盘的操作都是串行奉行的,不错径直根绝幻读问题。

 





Powered by 亚洲av无码一区二区三区天堂古代 @2013-2022 RSS地图 HTML地图