相关词语:数据库
redo log:日志模块(临时记录,相似于便签),InnoDB 引擎特有日志缓存
WAL(Write-Ahead Logging):写入方式优化
binlog:日志模块(归档日志),Server 层的日志日志
crash-safe:redo log带来的好处(MySQL 能够恢复到固定时间内任意一秒的状态)blog
WAL执行过程(redo log日志的存储方式):索引
write pos 是当前记录的位置,checkpoint 是当前要擦除的位置,它们之间的是“便签”上还空着的部分。若是 write pos 追上 checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推动一下。进程
redo log 与binlog的不一样点:事务
redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,全部引擎均可以使用。开发
redo log 是物理日志,记录的是“在某个数据页上作了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,好比“给 ID=2 这一行的 c 字段加 1 ”。it
redo log 是循环写的,空间固定会用完;binlog 是能够追加写入的。“追加写”是指 binlog 文件写到必定大小后会切换到下一个,并不会覆盖之前的日志。
首先update语句会把查询语句的流程先走一遍,区别就在与涉及到的两个日志模块:
update T set c=c+1 where ID=2;
1.链接数据库(链接器工做)
2.清空查询缓存(查询缓存工做)--》更新语句会清空更新表的查询缓存
3.分析词法和语法(分析器工做)--》获得这是一条更新语句
4.优化器决定使用ID这个索引(优化器工做)--》决定执行方案
5.执行器开始执行(执行器工做)--》找到这一行,进行更新
更新过程当中,执行器与引擎的交互:
此处将redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。
为何须要“两阶段提交“呢?
是为了让两份日志之间的逻辑保持一致。
这里就能够说说crash-safe功能是怎么实行的了。
crash-safe(例如):怎样让数据库恢复到半个月内任意一秒的状态?
binlog 会记录全部的逻辑操做,而且是采用“追加写”的形式。若是须要半个月内能够恢复,那么备份系统中必定会保存最近半个月的全部 binlog,同时系统会按期作整库备份。这里的“按期”取决于系统的重要性,能够是一天一备,也能够是一周一备。
当须要恢复到指定的某一秒时,好比某天下午两点发现中午十二点有一次误删表,须要找回数据,那你能够这么作:
1.找到最近的一次全量备份
2.从这个备份恢复到临时库
3.从备份的时间点开始,将备份的 binlog 依次取出来,重放到中午误删表以前的那个时刻。
而redo log 和 binlog 是两个独立的逻辑,若是不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者采用反过来的顺序。咱们看看这两种方式会有什么问题。
①,先写 redo log 后写 binlog。
假设在 redo log 写完,binlog 尚未写完的时候,MySQL 进程异常重启。因为咱们前面说过的,redo log 写完以后,系统即便崩溃,仍然可以把数据恢复回来,因此恢复后这一行 c 的值是 1。可是因为 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。所以,以后备份日志的时候,存起来的 binlog 里面就没有这条语句。而后你会发现,若是须要用这个 binlog 来恢复临时库的话,因为这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不一样。
②,先写 binlog 后写 redo log。
若是在 binlog 写完以后 crash,因为 redo log 还没写,崩溃恢复之后这个事务无效,因此这一行 c 的值是 0。可是 binlog 里面已经记录了“把 c 从 0 改为 1”这个日志。因此,在以后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不一样。
简单说,redo log 和 binlog 均可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。
总结:
redo log 用于保证 crash-safe 能力。
nnodb_flush_log_at_trx_commit 这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘。(能够保证 MySQL 异常重启以后数据不丢失)
sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。(能够保证 MySQL 异常重启以后 binlog 不丢失)
两阶段提交是跨系统维持数据逻辑一致性时经常使用的一个方案,即便你不作数据库内核开发,平常开发中也有可能会用到。
【附加问题】
按期全量备份的周期“取决于系统重要性,有的是一天一备,有的是一周一备”。那么在什么场景下,一天一备会比一周一备更有优点呢?或者说,它影响了这个数据库系统的哪一个指标?
【我的理解】
首先我理解的数据备份是为了恢复数据,假如须要恢复的是上周的数据,那么一周一备份就须要整周全备+须要恢复的数据时间点binlog来恢复,一天一备的话只须要当天的全备+这天某个时间段的binlog来恢复,那么一天已备份的优点就在于恢复丢失数据时的工做量。
其次就是数据丢失时的确认时间,天备只须要确认当天的binlog无缺无损,而周备须要确认一整周的binlog无缺。