MySQL的InnoDB怎么实现ACID的
事务的四点就是ACID
事务的几个特性就是表明要构成事务必须具备这些特性
原子性(Atomicity)
指的是事务是一个不可分割的执行单位,事务的执行,要么全部成功,要么全部失败;
一致性(Consistency)
事务前后的数据完整性必须一致;
隔离性(Isolation)
事务的隔离性指的是多个用户并发访问数据库的时候,数据库为每一个用户开启的事务,不能被其他的事务操作数据所干扰,多个并发事务之间要相互隔离;
持久性(Durability)
持久性指的是一个事务一旦被提交之后,它对数据库的改变就是永久性的,接下来即使发生故障也不应该对其有任何影响;
在说InnoDB实现事务之前有必要提一提几个概念
MySQL对于SQL的操作,往往是先建立在一个内存区域的,也就是Buffer Pool,为什么需要这个Buffer Pool呢?
如果说每次执行一条SQL,无论是增删改查,数据库都会优先从内存当中先看看有没有数据,如果没有数据,就访问数据磁盘,就行IO读取到内存当中,而这个访问数据磁盘的时候,并不是说每次只读一次就放到这个Buffer Pool;
每一次从db file当中读取数据,其实采用了页(page)的概念,每一次进行读取的时候,都是把所读到的数据所在page全部读取到buffer pool,这个page通常是16k
刚刚的情况是没有数据的情况下采取
先操作db file到Buffer Pool
那么如果Buffer Pool当中有数据的时候,
就会先修改Buffer Pool当中的数据
然后将修改的操作记录到Redo Log当中
每隔一段时间将Redo Log的记录执行
刷新磁盘当中的真实数据
Redo Log中文名称称之为重做日志
(这个就是保证事务的持久性操作的)
Redo Log在数据库突然重启的之后
Redo Log会检查是否还有数据未完成持久化
如果有,会自动执行
为啥需要Redo Log再写入到数据磁盘当中
这个其实与顺序IO和随机IO操作的性能有关
Redo Log的写入是顺序的IO,操作db file是采用随机IO
Redo Log的几个要点
1. 数据写入磁盘不用同步写入, 可以后台线程以异步的方式
进行写入。
2. Redo是以追加的方式记录, 将以前数据写入磁盘的随机IO
, 转换成顺序IO。
在Redo Log没真正刷新磁盘当中的数据的时候,Buffer Pool当中存在的数据,我们称之为脏页,Redo Log刷新数据磁盘的过程,我们称之为刷脏;
顺手来一张经典图
上图来自MySQL官方文档
Undo Log与Redo Log
一起就完成了事务的原子性,Undo Log是记录操作之前的数据集,Undo Log我们称之为撤销日志,也就是事务操作失败的时候,进行回滚的日志;
Undo Log应遵从以下两个条件:
1. 事务在修改了某一个数据的时候,应该是新数据未写入磁盘之前,现将Undo Log操作完成;例如:事务T修改了数据库元素X, 形式如<T, X, v>的日志记录必须在X的新值写到磁盘之前写入磁盘中。
2. 如果事务提交, 则COMMIT日志记录必须在事务改变的所
有数据库元素先写到磁盘之后写到磁盘中, 但应尽快;
以上就是MySQL的的Atomicity与Durability特性,那么我们还缺两个;
Isolation这个特性不得不提到MVCC与锁机制问题
·(一个事务)写操作对(另一个事务)读操作情况下:MVCC
保证隔离性;
·(一个事务)写操作对(另一个事务)写操作情况下:锁机制保证隔离性;
MVCC:全称是Multi-Version Concurrency Control(多版本的并发控制协议),采用版本控制,让不同的事务读取到的数据版本是不一样的一种机制(MVCC是一种无锁的高效解决办法,A事务在进行写操作的时候,B事务可以进行读取数据,并且可以保证数据的隔离性问题);
MVCC实现的原理
Innodb表在记录行上其实还有三个不可见的字段的
a) 6字节的事务ID
b) 7字节的指向回滚段的指针
c) 6字节的ROW_ID
锁机制:A事务在修改数据之前,需要获取相对应的锁;获得锁之后,A事务才可以进行修改数据,如果此时有B数据想要进来操作A事务正在操作的数据,那么需要等待A事务先释放锁资源,才可以进行对于数据的操作;(A事务只有在commit或者rollback之后才会释放锁);
对于事务的Consistency,只有在事务的前三个特性完成的前提下,才可以完成相应的功能;