82-log
- Mysql分层结构,分为Server层和Engine两层,进行了“解耦”。mysql_engine才可以插件化
- redo, undo, binlog
1. sql入库流程
- 执行器先从Engine中找数据。如果没有,查询DB写入Buffer_Pool
- 执行器执行sql,同时记录
redo_log, undo_log
,此时处于prepare阶段。再通知执行器执行完成 - 执行器记录
bin_log
,并调用Engine进行commit - disk更新。
redo_log, undo_log
刷到OS_cache
2. Buffer_Pool
- 缓存MySQL磁盘数据的内存空间
- 内存操作,快
- Buffer_Pool减少Disk_IO
# 事务A
update user set age = 2
# 事务B
update user set age = 3
# 事务C
update user set age = 4
问题:断电了,数据一致性?=>(redo_log)
3. redo_log(前滚日志)
- Aim:保证Trx持久性。恢复Buffer_Pool
- InnoDB就可以保证即使DB发生异常重启,之前的记录也不会丢失,叫做crash-safe
- 所属InnoDB引擎,物理日志
- redo_log是磁盘顺序写。WAL(Write-ahead logging),预写式日志,数据刷盘是磁盘随机写,磁盘的顺序写比随机写高效的多
- redo_log固定大小,是循环写的过程。即先记下来,抽空异步写到磁盘日志文件上
- 磁盘顺序写进一步提高效率,引入redo_log_buffer
加深理解
酒店的客人赊账账本。一天的流水先记录到小黑板上,夜里没人了再更新到账本上。
1. Mysql挂了
- OS挂了。MySQL服务端是一个进程。Buffer_Pool、OS_cache数据全丢失
- OS没挂。Buffer_Pool数据丢失,OS_cache数据没丢失
2. redo_log落盘机制
# 0. 延迟写,延迟刷
innodb_flush_log_at_trx_commit = 0
# 1. 实时写,实时刷
innodb_flush_log_at_trx_commit = 1
# 2. 实时写,延迟刷。减少data在buffer_copy
innodb_flush_log_at_trx_commit = 2
1. 延迟写,延迟刷
- 事务提交时,只会把数据写到redo_log_buffer,让后台线程定时去将redo_log_buffer里面的数据刷到disk
- 效率最高,风险最高
2. 实时写,实时刷
- 事务提交之前,每次都会将数据从redo_log刷到磁盘中去
- 效率最低,风险最低
3. 实时写,延迟刷
- commit,redo_log写到OS_cache,每秒执行一次刷新磁盘操作
- Mysql进程挂了,OS没挂,数据完好
- 效率比较高,风险比较低
4. undo_log(回滚日志)
- Aim
- 保证Trx原子性(回滚)
- InnoDB存储引擎中,还用undo_log来实现多版本并发控制(MVCC)
- 所属InnoDB引擎,逻辑日志
- delete一条记录,undo_log中会记录一条对应的insert记录
- insert一条记录,undo_log中会记录一条对应的delete记录
- update一条记录,记录一条对应相反的update记录
- undo_log默认存全局表空间,理解为插入一条undo_log和插入一条普通数据类似。写undo_log同样也要写入redo_log
5. bin_log(二进制日志)
- Aim
- 提供了崩溃恢复的能力
- MySQL高可用(主从复制)依赖binlog复制
- 所属mysql_server,逻辑日志,记录所有的逻辑
- 恢复数据的过程
- 找到最近一次的全量备份数据
- 从备份的时间点开始,将备份的binlog取出来,重放到要恢复的那个时刻
1. 落盘策略
# 每次提交事务前,将binlog写入OS_cache,由OS控制什么时候刷到磁盘
sync_binlog = 0
# 采用同步写磁盘的方式来写binlog,不使用OS_cache来写binlog
sync_binlog =1
# n次事务提交之后,调用一次fsync将OS_cache中的binlog强制刷到磁盘
sync_binlog = N
2. 区别redo_log
- binlog是Server层的日志。所有Engine都具备
- redo_log是InnoDB的日志。如果不使用InnoDB引擎,则没有redo_log
- binlog是逻辑日志,记录的是对哪一个表的哪一行做了什么修改(sql记录)
- redo_log是物理日志,记录的是对哪个数据页中的哪个记录做了什么修改,可以理解成对磁盘上的哪个地址的内容做了修改
- binlog是追加写
- redo_log是循环写,日志文件有固定大小,会覆盖之前的数据
3. 取代bin_log
- binlog的生态已经建立。MySQL高可用依赖binlog复制
- binlog不是MySQL的瓶颈,花时间在没有瓶颈的地方没必要