设为首页 加入收藏

TOP

MySQL使用可重复读作为默认隔离级别的原因
2017-02-21 08:15:45 】 浏览:6339
Tags:MySQL 使用 复读 作为 默认 隔离 级别 原因

SERIALIZABLE > RR > RC > Read-Uncommited


在SQL标准中,前三种隔离级别分别解决了幻象读、不可重复读和脏读的问题。那么,为什么MySQL使用可重复读作为默认隔离级别呢?


BinlogMySQL的逻辑操作日志,广泛应用于复制和恢复。MySQL?5.1以前,StatementBinlog的默认格式,即依次记录系统接受的SQL请求;5.1及以后,MySQL提供了RowMixed两个Binlog格式。


MySQL?5.1开始,如果打开语句级Binlog,就不支持RCRead-Uncommited隔离级别。要想使用RC隔离级别,必须使用MixedRow格式。


那么,为什么RC隔离级别不支持语句级Binlog呢?我们关闭binlog,做以下测试。


由以上测试知,RC隔离级别下,会话2执行时序在会话1事务的语句之间,并且会话2的操作影响了会话1的结果,这会对Binlog结果造成影响。


由于Binlog中语句的顺序以commit为序,如果语句级Binlog允许,两会话的执行时序是


由上可知,在MySQL?5.1及以上的RC隔离级别下,语句级BinlogDR上执行的结果是不正确的!


那么,MySQL?5.0呢?5.0允许RC下语句级Binlog,是不是说很容易产生DB/DR不一致呢?


事实上,在5.0重复上述一个测试,并不存在这个问题,原因是5.0RC5.1RR使用类似的并发和上锁机制,也就是说,MySQL?5.0RC5.1及以上的RC可能存在兼容性问题


下面看看RR是怎么解决这个问题的。


导致RC隔离级别DB/DR不一致的原因是:RC不可重复读,而Binlog要求SQL串行化!


RR下,重复以上测试


RC隔离级别不同的是,在RR中,由于保证可重复读,会话2delete语句会被会话1阻塞,直到会话1提交。


RR中,会话1语句update?t2?set?c2?=?3?where?c1?in?(select?c1?from?t1)会先在t1的记录上S锁(5.1RC中不会上这个锁,但5.0的RC会),接着在t2的满足条件的记录上X锁。由于会话1没提交,会话2delete语句需要等待会话1S锁释放,于是阻塞。


因此,在RR中,以上测试会话1、会话2的依次执行,与Binlog的顺序一致,从而保证DB/DR一致。


除了保证可重复读,MySQLRR还一定程度上避免了幻象读(幻象读是由于插入导致的新记录)。(为什么说一定程度呢?参考第3节可重复读和串行化的区别。)


由上述例子知,会话2的插入操作被阻塞了,原因是RR隔离级别中,除了记录锁外,还会上间隙锁(gap)。例如,对于表t1update?t2?set?c2?=?20?where?c1?in?(select?c1?from?t1)以上的锁包括:


(-∞,?1),?1,?(1,?10),?10,?(10,?+∞)


由于对t1做全表扫描,因此,所有记录和间隙都要上锁,其中(x,y)表示间隙锁,数字表示记录锁,全部都是S锁。会话2insert操作插入5,位于间隙(1,10),需要获得这个间隙的X锁,因此两操作互斥,会话2阻塞。


SQL标准的RR并不要求避免幻象读,而InnoDB通过gap锁来避免幻象,从而实现SQL的可串行化??保证Binlog的一致性。


要想取消gap?lock,可使用参数innodb_lock_unsafe_for_binlog=1,默认为0


InnoDBRR可以避免不可重复读和幻象读,那么与串行化有什么区别呢?


由上述会话1中,连续两次读不到数据,但更新却成功,并且更新后的相同读操作就能读到数据了,这算不算幻读呢?


其实,RR隔离级别的防止幻象主要是针对写操作的,即只保证写操作的可串行化,因为只有写操作影响Binlog;而读操作是通过MVCC来保证一致性读(无幻象)。


然而,可串行化隔离级别要求读写可串行化。使用可串行化重做以上测试。


设置为串行化后,会话2的插入操作被阻塞。由于在串行化下,查询操作不在使用MVCC来保证一致读,而是使用S锁来阻塞其他写操作。因此做到读写可串行化,然而换来就是并发性能的大大降低。


MySQL使用可重复读来作为默认隔离级别的主要原因是语句级的BinlogRR能提供SQL语句的写可串行化,保证了绝大部分情况(不安全语句除外)的DB/DR一致。


另外,通过这个测试发现MySQL?5.05.1RC下表现是不一样的,可能存在兼容性问题。?


http://dev.mysql.com/doc/refman/5.1/en/binary-log-mixed.html


http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html


http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html


http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_locks_unsafe_for_binlog


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇深入理解MySQL的四种隔离级别 下一篇Linux下MongoDB简介及部署使用

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目