聊聊MySQL 为啥会使用可重复读(Repeatable-Read)作为默认隔离级别

今天主要来聊下mysql 选择可重复读作为默认的隔离级别的原因

1. 什么是可重复读?

简单来说就是在同一个事务中多次读取同样的记录的结果是一样的,Innodb使用MVCC来实现。这里就不展开说了。

我们知道大多数数据库系统比如:Oracle、SQLServer等数据库默认的事务隔离级别是提交读,但是MySQL不是。MySQL 把可重复读作为默认的隔离级别,这和数据库二进制文件的格式有关,我们知道对于数据库的修改操作会记录到一个二进制文件里面(当然,需要开启),这个二进制文件 的作用主要在于服务器故障后可以进行基于时间点的数据恢复,另外就是用于主从复制。下面来看下bin_log 主要有哪几种类型的格式。

2. 二进制文件的几种格式

  1. statement 记录的是可能改变数据sql语句
  2. row 记录的是每行数据的变更
  3. mix 混合型,默认会使用statement格式记录二进制文件,在某些特殊情况(比如使用了一些不确定性的函数(rand(),UUID(),user() 等,这个时候可能会导致主从数据不一致的情况。) 使用row。

另一方面,如果使用提交读(Read Committed)作为默认的隔离级别且二进制文件的格式是statement的,主从同步的时候会导致部分丢失更新的现象。 下面我们来具体解释下为啥出现这种情况。

读提交(Read Committed):大部分数据库采用的默认隔离级别。一个事务的更新操作结果只有在该事务提交之后,另一个事务才可以读取到同一笔数据更新后的结果。
丢失更新:两个不同事物同时获得相同数据,然后在各自事务中同时修改了该数据,那么先提交的事务更新会被后提交事务的更新给覆盖掉,这种情况事务A的更新就被覆盖掉了、丢失了。

3. 测试

我们先来看下在Read Committed (可提交读)的情况下会产生的问题。为了测试暂时关闭binlog(二进制文件),不然写binlog文件会报错。
下面来看个例子:
先来创建两张测试表

create table t1 (c1 int,c2 int) engine = innodb;
create table t1 (c1 int,c2 int) engine = innodb;
insert into t1  values (1,1),(2,2);
insert into t2  values (1,1),(2,2);
并发事务.png

在上面的测试中我们发现在可提交读这个隔离级别下,session2的操作穿插在session1的执行过程中,并最终影响了session1的执行结果。
由于binlog中的语句以commit为序,如果bin log 的格式是Statement (sql语句),两个会话的执行顺序是:

// session2;
set tx_isolation='read-committed';
delete from t1 where c1 = 2;
commit;

//session1
set tx_isolation='read-committed';
Begin;
update t2 set c2 = 3 where c1 in (select c1 from t1);
update t2 set c2 = 4 where c1 in (select c1 from t1);
select * from t2;
+------+------+
| c1   | c2   |
+------+------+
|    1 |    4 |
|    2 |    2 |
+------+------+
2 rows in set (0.00 sec)
commit;

由此可知,在提交读这个隔离级别下,语句级bin log的执行结果是不正确的。
下面我们在REPEATABLE-READ(可重复读)下重新上面的测试。


并发事务.png

由于session2在执行delete操作时被阻塞了,直到session1提交完才能执行。在可重复读隔离级别下,session1中的update t2 set c2 = 3 where c1 in (select c1 from t1); 这条语句时会给c1中的记录加行锁(实验表明:t1和t2表共同的那些记录),使得session2中的删除操作被阻塞直到session1提交完成,这样的话就会使得binlog中记录的sql语句顺序和执行的顺序是一致的,从而避免主从同步时丢失更新的现象。

共享锁【S锁】:又称为读锁,若事务T对数据对象A加上S锁,则事务T可以读A但是不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排他锁【X锁】:又称写锁,若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释>放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
间隙锁【gap lock】: 锁加在不存在的空闲空间,可以是两个索引记录之间,也可以是第一个索引记录之前或者最后一个索引记录之后的空间。唯一作用是防止其他事务的插入操作,以此来达到防止幻读的发生,所以间隙锁部分共享锁和排他锁。
Next-Key Lock:行锁与间隙锁组合起来就叫做Next-Key Lock。

4. 总结:

MySQL使用可重复读(Repeatable-Read)作为默认的存储引擎主要是因为老版本的MySQL二进制文件的各种只支持statement这一种格式,这种格式的二进制文件如果使用提交读(Read-Committed)作为默认的隔离级别会导致丢失更新的问题,所以MySQL使用了可重复读(Repeatable-Read)作为默认的存储引擎。如果把二进制文件的格式改成row,那也可以使用提交读(Read-Committed)作为隔离级别,可以提高数据库的并发性能。

注:这里的实验没有开启间隙锁。查看间隙锁是否开启:show variables like 'innodb_locks_unsafe_for_binlog'; 如果值为off则表示没有开启。

先写到这里,如果有小伙伴需要补充的欢迎在下面给我留言哦,看到会及时回复的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355