最近准备面试复习Mysql八股,对mysql的日志系统,事务,锁,MVCC有一些感悟,希望各位前辈指正。
事务的ACID 分别 ( A 原子性 C 一致性 <--> undo log )
(D 持久性 <-->binlog 和Innodb的redolog)
(I 隔离性 <--> 锁 MVCC)
一、
undo log 通过回滚段的方式管理事务,保证事务的原子性和一致性
二、
binlog 和 InnoDB的redo log 通过记录操作日志的方式,保持数据库持久性,并且 使用 两阶段提交 机制保证两个日志是一致的,binlog多用于集群,主从,备份;redolog独特的crash-safe能力可以用来做灾难恢复
三、
说道隔离性就不得不说起隔离级别,那mysql是如何实现隔离级别的,又解决了什么问题呢?在回答这个问题之前,需要先明确几个概
快照读和当前读
-
快照读
简单的查询,不包括(
select ...for update
select ... lock in share mode) 这两种的查询,都直接生成readView,且不会对记录加锁。
-
当前读
读取最新版本,要先获取记录的锁。
如下sql类型:
select ...for update
select ... lock in share mode
update 、 delete 、insert
Innodb的行锁:
记录锁、间隙锁、临键锁
MVCC
MVCC全称是多版本并发控制 (Multi-Version Concurrency Control),只有在InnoDB引擎下存在。MVCC机制的作用其实就是避免同一个数据在不同事务之间的竞争,提高系统的并发性能。
它的特点如下:
-
允许多个版本同时存在,并发执行。
-
不依赖锁机制,性能高。
-
只在读已提交和可重复读的事务隔离级别下工作。
并发事务导致的问题:
脏读 不可重复读 幻读
为了解决上述并发事务导致的问题,引入四种隔离级别 读未提交 读已提交 可重复读 串行化
隔离级别是一种概念,不同的数据库会有不同的实现,下面给出通过加锁的实现方式。例如
-
读已提交 通过行级锁来解决脏读现象,解决不了其他两个问题
-
可以通过间隙锁解决不可重复度,但是没办法解决幻读
-
因此引入临键锁解决幻读的问题
隔离级别解决并发事务,加锁可以解决,但是mysql引入MVCC,通过无锁的方式来实现读写并发控制。MVCC基于隐藏字段,undolog,readView实现。ReadView的机制只在Read Committed和Repeatable Read隔离级别下生效,所以只有这两种隔离级别才有MVCC。在Read Committed隔离级别下,每次读取数据时都会生成ReadView;而在Repeatable Read隔离级别下只会在事务首次读取数据时生成ReadView,之后的读操作都会沿用此ReadView
总结:
所谓隔离级别,就是为了解决并发访问引出来得概念。其实可以通过无脑加读锁,写锁解决,但是性能会降低。所以mysql的innodb引入mvcc,通过无锁的方式在RC RR 隔离级别下,解决了不可重复读和部分幻读。
快照读基于mvcc实现。 当前读基于锁实现。
还有关于锁和索引的关系还没太理顺明白