MSQL 有三大日志,binlog, redolong ,undo log ,
binlog ,记录的是语句,主要用来做集群数据同步的,像主从复制之间的一些数据同步。
redolog ,是innodm独有的日志,记录了数据的修改,保证了持久性,在数据库崩溃的时候能够恢复数据。
undo log , 是数据库的版本链,能够回退日志,保证了原子性,同时配置MVCC机制,实现了多版本并发控制。
Buffer Pool?
这是一个引擎层的缓冲池,在查询的时候会讲一些数据缓冲在缓冲池,对于修改,如果在缓冲池就有这个数据,则会在缓冲池中修改,标记为脏页,以及undo log 也是先刷新到Buffer Pool 里面的,然后在某个适合的时机刷盘到磁盘里面。
Innodb 通过三种链表来管理缓页:
- Free List (空闲页链表),管理空闲页;
- Flush List (脏页链表),管理脏页;
- LRU List,管理脏页+干净页,将最近且经常查询的数据缓存在其中,而不常查询的数据就淘汰出去。
InnoDB 对 LRU 做了一些优化,我们熟悉的 LRU 算法通常是将最近查询的数据放到 LRU 链表的头部,而 InnoDB 做 2 点优化:
- 将 LRU 链表 分为 young 和 old 两个区域,加入缓冲池的页,优先插入 old 区域;页被访问时,才进入 young 区域,目的是为了解决预读失效的问题。
- 当**「页被访问」且「 old 区域停留时间超过 innodb_old_blocks_time 阈值(默认为1秒)」**时,才会将页插入到 young 区域,否则还是插入到 old 区域,目的是为了解决批量数据访问,大量热数据淘汰的问题。
关于redo log 的流程:
在事务提交时,只要先将 redo log 持久化到磁盘即可,可以不需要等到将缓存在 Buffer Pool 里的脏页数据持久化到磁盘。
redo log 也有自己的内核缓存—— redo log buffer
所以它的流程是 -> buffer pool -> redo log buffer -> 磁盘
两个缓冲,前一个是在用户态下的,后一个是在内核态的。
为什么需要redo log ?
- 实现事务的持久性,让 MySQL 有 crash-safe 的能力,能够保证 MySQL 在任何时间段突然崩溃,重启后之前已提交的记录都不会丢失;
- 将写操作从「随机写」变成了「顺序写」,提升 MySQL 写入磁盘的性能。
redo log 什么时候刷盘?
- MYSQL正常关闭时;
- 当 redo log buffer 中记录的写入量大于redo log buffer 内存空间的一半时,会触发刷盘;
- InnoDB 的后台线程每隔一秒,讲redo log buffer 持久化到磁盘;
- 每次事务提交时会有一个策略,这个策略是可以选择的,有三个策略,分别是只保存在redo log buffer ,保存在系统内核的redo log 缓冲区,保证在磁盘,这三种。
redo log 写满了怎么办?
有一个日志文件组,一个写入点,一个读取点,假如满了,会阻塞,把缓冲池的脏页给刷新到磁盘中,然后对redo log 进行标记擦除。然后可以正常的运行,执行新的更新操作。
redo log 和 undo log 有什么区别?
redo log 是InnoDB独有的日志,bin log 是全部引擎都会有的日志,其次binlog 可以说记录的是sql语句,逻辑日志,而redo log 记录的是物理日志,在那个数据页那条数据做了什么修改。
binlog 是追加写,而redo log是循环写,所以binlog 可以说是坐的一个全局日志。binlog用于备份恢复,主从复制,redo log 用于故障恢复。
主从复制是如何实现的?
MYSQL的主从复制依赖于binlog,也就是记录MYSQL上的所有变化并以二进制保存在磁盘上,复制的过程就是将binlog中的数据从主库传输在从库上。
主要分三步:1.主库写binlog 2.异步线程同步binlog 3.从库同步数据
MYSQL主从复制有哪些模型?
同步复制:主库的事务线程需要同步等待所有的从库复制成功响应,才返回,性能较差。
异步复制:不会等待,直接返回,这小效率最高,但是主机宕机会发生数据丢失。
半同步复制:只要等到一个从库的复制成功响应,就放回,介于两种之间。
binlog 什么时候刷盘?
它也是有两个缓冲区,一个是binlog buffer ,一个是系统内核缓冲区
一般有这么几种策略: 0-每次只写到系统内核区 1 -每次事务提交都刷到磁盘 2- N 累计N个事务才进行刷盘。
两阶段提交
- prepare 阶段:将 redo log 对应的事务状态设置为 prepare,然后将 redo log 刷新到硬盘;
- commit 阶段:将 binlog 刷新到磁盘,接着调用引擎的提交事务接口,将 redo log 状态设置为 commit(将事务设置为 commit 状态后,刷入到磁盘 redo log 文件);