为什么Mysql 默认的隔离级别是可重复读?

这是个历史问题,主要就是主从复制的问题了,说到主从复制就肯定离不开bin log

binlog 的三种格式:

  1. Statement:记录修改的sql
  2. raw:记录每行实际数据的变更
  3. mixed:1,2的混合

mysql5.1之前binlog的记录方式只支持statement方式,而这种格式在读已提交的隔离级别下主从复制是有bug的,所以将可重复读作为默认隔离级别!

接下来要讲bug是怎么发生的:

  1. 首先通过命令,查询一下默认隔离级别。
 show variables like 'transaction_isolation';
  1. 设置session隔离级别为“读提交”
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
  1. 在读提交的隔离级别下,开启两个会话:按照下面的顺序执行命令,最后得到的数据库只有一条记录
    在这里插入图片描述

  2. mysql5.1之前binlog的记录方式只支持statement方式,用于恢复和主从复制。主库就是将每次数据库的sql(增删改)修改在提交以前以二进制编码的形式保存到日志文件中。那么根据上图展示的情况,在提交前才会写入日志文件,那么日志文件中的sql语句顺序就会是 先插后删,所以在从库中是没有数据的,而在主库中是有数据的(因为session1先开始的事务,会触发锁,导致session2中的事务在session1提交之后才能生效)。

  3. 如何解决?
    (1) 隔离级别设置为可重复读,在该隔离级别下引入间隙锁。当session1执行delete语句时,会锁住间隙,那么session2执行的插入语句就会堵塞住!
    (2) 将binlog的格式修改为row格式,此时就会是基于行的复制,自然就不会出现sql不一致的情况,但是该格式是在mysql5.1版本后开始引入。

所以,mysql选择了可重复读作为默认的隔离级别。

在实际项目中应该使用哪种隔离级别?

  1. 正常情况下应该使用读已提交,相对于可重复读的优点如下:
    (1) 因为可重复读存在间隙锁,所以可重复读导致出现死锁的概率比读已提交大。
    (2) 在可重复读隔离级别下,条件列未命中索引会触发锁表,而读已提交只是行锁
  2. 个别情况:例如对账单:
    需要对照余额表和账单表数据时,希望读出来的余额不受最新操作影响,就要使用到可重复读的隔离级别了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值