【MySQL】事务默认隔离级别
MySQL事务默认隔离级别
MySQL 数据库事务的默认隔离级别为 Repeatable Read 简称 RR。
Oracle 数据库事务的默认隔离级别为 Read Committed 简称 RC。
MySQL 在 5.0 这个版本以前,binlog 只支持 STATEMENT
这种格式!而这种格式在读已提交 Read Commited 这个隔离级别下主从复制是有 BUG 的,因此 MySQL 将可重复读 Repeatable Read 作为默认的隔离级别!
由于历史原因
主从复制,是基于binlog复制的!
binlog 三种格式,分别是
- statement:记录的是修改 SQL 语句(基于语句的主从复制)
- row:记录的是每行实际数据的变更(基于行锁的主从复制)
- mixed:statement 和 row 模式的混合
1、主从不一致性的问题
原因就是在主(master)上执行的顺序为先删后插!而此时 binlog 为 STATEMENT 格式,它记录的顺序为先插后删!从(slave)同步的是 binlog,因此从机执行的顺序和主机不一致!就会出现主从不一致!
解决方案有两种!
-
隔离级别设为「可重复读 Repeatable Read」,在该隔离级别下引入间隙锁。当
Session 1
执行delete语句时,会锁住间隙。那么,Ssession 2
执行插入语句就会阻塞住! -
将binglog 的格式修改为 row 格式,此时是基于行的复制,自然就不会出现 SQL 执行顺序不一样的问题!奈何这个格式在 MySQL 5.1 版本开始才引入。因此由于历史原因,MySQL 将默认的隔离级别设为「可重复读 Repeatable Read」,保证主从复制不出问题!
2、对比
2.1 读未提交和串行化
- 「读未提交 Read UnCommitted」一个事务读到另一个事务未提交读数据,问题不言而喻,脏数据、不可重复读和幻读都解决不了。
- 「串行化 Serializable」每个次读操作都会加锁,快照读失效,一般是使用 MySQL 自带分布式事务功能时才使用该隔离级别(一般不使用,因为这是XA事务,是强一致性事务,性能不佳!互联网的分布式方案,多采用最终一致性的事务解决方案)
2.2 可重复读和读已提交
- 可重复读 Repeatable Read,简称为 RR;
- 读已提交 Read Commited,简称为 RC;
缘由一:在 RR 隔离级别下,存在间隙锁,导致出现死锁的几率比 RC 大的多。
ps
:在 RC 隔离级别下并不是不会出现死锁,只是出现几率比 RR 低而已。
缘由二:在 RR 隔离级别下,条件列未命中索引会锁表!而在 RC 隔离级别下,只锁行。
缘由三:在 RC 隔离级别下,半一致性读 semi-consistent 特性增加了 update 操作的并发性。
所谓半一致性读就是,一个 update 语句,如果读到一行已经加锁的记录,此时 InnoDB 返回记录最近提交的版本,由 MySQL 上层判断此版本是否满足 update 的 where 条件。若满足(需要更新),则 MySQL 会重新发起一次读操作,此时会读取行的最新版本(并加锁)!