• 【转载】Mysql默认的事务隔离级别是可重复读(Repeatable Read),那互联网项目中Mysql使用读已提交(Read Commited)这个隔离级别


    为什么Mysql不选择读已提交(Read Commited)作为默认隔离级别,而选择可重复读(Repeatable Read)作为默认的隔离级别呢?

    这个是有历史原因的,当然要从我们的主从复制开始讲起了!

    主从复制,是基于什么复制的?
    是基于binlog复制的!这里不想去搬binlog的概念了,就简单理解为binlog是一个记录数据库更改的文件吧~

    binlog有几种格式?

    statement:记录的是修改SQL语句

    row:记录的是每行实际数据的变更

    mixed:statement和row模式的混合

    那Mysql在5.0这个版本以前,binlog只支持STATEMENT这种格式!而这种格式在读已提交(Read Commited)这个隔离级别下主从复制是有bug的,因此Mysql将可重复读(Repeatable Read)作为默认的隔离级别!

    接下来,就要说说当binlog为STATEMENT格式,且隔离级别为读已提交(Read Commited)时,有什么bug呢?如下图所示,在主(master)上执行如下事务。

    主从复制怎么实现
    session1 session2 怎么实现

    这样,你就出现了主从不一致性的问题!原因其实很简单,就是在master上执行的顺序为先删后插!而此时binlog为STATEMENT格式,它记录的顺序为先插后删!从(slave)同步的是binglog,因此从机执行的顺序和主机不一致!就会出现主从不一致!
    如何解决?
    解决方案有两种!
    (1)隔离级别设为可重复读(Repeatable Read),在该隔离级别下引入间隙锁。当Session 1执行delete语句时,会锁住间隙。那么,Ssession 2执行插入语句就会阻塞住!
    (2)将binglog的格式修改为row格式,此时是基于行的复制,自然就不会出现sql执行顺序不一样的问题!奈何这个格式在mysql5.1版本开始才引入。因此由于历史原因,mysql将默认的隔离级别设为可重复读(Repeatable Read),保证主从复制不出问题!

    那么,当我们了解完mysql选可重复读(Repeatable Read)作为默认隔离级别的原因后

    接下来我们将其和读已提交(Read Commited)进行对比,来说明为什么在互联网项目为什么将隔离级别设为读已提交(Read Commited)

    对比

    ok,我们先明白一点!项目中是不用读未提交(Read UnCommitted)串行化(Serializable)两个隔离级别,原因有二

    • 采用读未提交(Read UnCommitted),一个事务读到另一个事务未提交读数据,这个不用多说吧,从逻辑上都说不过去!
    • 采用串行化(Serializable),每个次读操作都会加锁,快照读失效,一般是使用mysql自带分布式事务功能时才使用该隔离级别!(笔者从未用过mysql自带的这个功能,因为这是XA事务,是强一致性事务,性能不佳!互联网的分布式方案,多采用最终一致性的事务解决方案!)

    也就是说,我们该纠结都只有一个问题,究竟隔离级别是用读已经提交呢还是可重复读?

    为了便于描述,下面将

    • 可重复读(Repeatable Read),简称为RR;
    • 读已提交(Read Commited),简称为RC;

    缘由一:在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多!

    缘由二:在RR隔离级别下,条件列未命中索引会锁表!而在RC隔离级别下,只锁行

    缘由三:在RC隔离级别下,半一致性读(semi-consistent)特性增加了update操作的并发性!

  • 相关阅读:
    java八大数据类型
    变量,常量,作用域
    位运算符
    可变参数
    重写
    javascript中各种循环总结
    前端高效emmit快捷键
    移动端列表页布局
    sublime text3中添加插件CSScomb方法
    友元类头文件互相包含问题
  • 原文地址:https://www.cnblogs.com/smallwangmusk/p/11335205.html
Copyright © 2020-2023  润新知