很久没更新博客了,这次简单聊一下我自己对mysqlACID原理的理解
名词解释
-
A(atomicity):原子性
-
C(consistency) :一致性
-
I(isolation):隔离性
-
D(durability):持久性
ACID的实现原理
- A(atomicity):使用undo log日志实现,原子性要么都成功,要么都失败,会记录每一次的操作记录的undo log日志,后面发生异常时在从undo log把事物回滚掉
- C(consistency):一致性是根据原子性+个理性+持久性组合下完成的
- I(isolation):锁
- D(durability):redo log日志实现
mysql数据更新的流程
- 获取到原始数据,首先在执行引擎汇总查找数据,如果是在内存中则直接返回,否则从磁盘汇总load到内存,然后返回
- 更新数据,从执行引擎获取到数据后对其进行修改,然后调用引擎接口把修改后的数据重新写入到引擎中
- 重新写入数据,首先把上面的修改后的数据写入到内存,然后写入redo log中这里是二阶段中的一阶段prepare,操作完成后通知执行器完成
- 写入bin log日志,这里还是二阶段中的一阶段的另一个分支写binlog日志
- 提交事物,最后执行器调用引擎的提交事物接口,这里也就是二阶段中的二阶段,最后把redo log改为commit状态,最终完成
redo log写入流程(INNODB)
- 写redo log日志,更新到内存
- 用户态innodb引擎的log buffer
- 内核态os buffer
- 异写调研内核态接口fsync写到磁盘中,也就是redo log磁盘文件
- 当有一条事物操作数据时,在innodb数据库引擎中会先把数据写到relog中,更新到内存,具体是怎么做的呢,这里分为用户态和内核态,我们的内存操作都是在用户态执行,然后磁盘是在内核态中,首先这里面写的过程分为先在innodb引擎中写relog,然后在写log buffer,内核态的os buffer,最后从os buffer中每秒的调用fasyc异写入到磁盘。
- 最后写到磁盘的有三种方式,通过参数配置,innodb_flush_log_at_trx_commit,可以使用命令查询这个设置的是什么
show variables like 'innodb_flush_log_at_trx_commit';
- 先写到log buffer-》os buffer-》每秒调用fsync写入磁盘(性能最高,不安全)-〉参数值:0
- 直接写到os-buffer-》每秒调用fsync写入磁盘(性能较高,较安全,推荐)-〉参数值:1
- 直接写到os-buffer并且调用fsync写入磁盘(性能低,很安全)-〉参数值:2
附上一张binlog写到磁盘的图
write操作是把日志文件的临时文件先写到内核开辟的一个内存空间中
fsync才是实际的把binlog file在内核的空间中异写到磁盘中
write和fsync都有一个机制控制是怎么样的写,由mysql参数的sync_binlog控制
sync_binlog参数,有3种,0,1,N
0:只是write,不进行fsync(但是不代表不写磁盘的意思,而是有后台线程自己控制时间写到磁盘)
1:每次都进行fsync操作,直接就写到磁盘了,这样做的安全性最高的,不会存在数据丢失的情况,推荐此种,但是如果出现master-slave出现了主从同步延迟的则可以权衡考虑是否调整
N:不是每次进行fsync,而是在write到binlog file中积累了N次事物后在进行fsync异写
有时间的话,下一期会讲一下mysql中的MVCC的实现原理