更新语句涉及的模块:
连接器建立连接、
分析器解析语句要做什么、
优化器得出怎么做,
执行器调用存储器执行命令,
redo log:重做日志,
bin log:归档日志
1、redo log[存储引擎有的日志]
当业务繁忙时,执行一次更新语句 要到库表中若干个记录中查询要更新的记录,再执行更新操作,整个过程的IO成本,查找成本都很高。
所以mysql这样做:
当有一条记录要更新时,InnoDB先将记录写到 redo log 中,并更新内存,此时更新就算完成,当系统空闲时,InnoDB会将更新写进磁盘。
write pos 是当前写入磁盘的位置,写到 3后会回到0,这样循环下去。
checkpoint 是当前 清除记录的位置,当 write pos 追到 check point 时,表示,日志满了,此时不能执行新的更新操作,得停下来清楚一些更新日志。
有了 redo log, InnoDB保证了即使数据库发送异常,之前提交的记录也不会丢失,这个称为 crash-safe
2、redo log 和 binlog区别
- redo log 是InnoDB引擎特有的,binlog是mysql server层实现,所以存储引擎都可以使用。
- redo log是物理日志,记录了某个数据有什么修改
binlog 是逻辑日志,记录这个语句的原始逻辑,如:给ID=2的c字段+1 - redo log 是循环写的,空间固定会用完,
binlog 是追加写的,写到一定大写后会切换到下一个,不会覆盖以前的日志。 - redo log 有 crash-safe的能力,binlog则没有
3、更新语句的执行流程
update T set c=c+1 where id = 2
1、执行器,通过引擎 获取 id = 2 的记录,如果内存中有直接返回,没有从磁盘中读取再写入内存后返回
2、将记录 c+1后,得到新数据,再调用引擎接口写入这一行新数据。
3、引擎将新数据 更新到内存和redo log ,此时 redo log状态为 prepare,然后告知执行器完成了,随时提交事务。
4、执行器生成操作的 binlog ,并写入磁盘
5、执行器调用引擎提交事务的接口,将 redo log的状态改为 commit ,更新完成。
4、怎么把数据库恢复到半月内的任意一秒
binlog是采用追加式 记录所有的逻辑操作,并且系统会做整库的备份。
- 将最近的全量备份恢复到临时库中
- 从备份中 按照时间依次取出 binlog,找到要恢复的那一时刻的 binlog日志
这样临时库和要恢复的库一样了,把表数据从临时库取出来,按需要恢复
5、redo log为什么两个阶段提交
将 redo log 的写入拆成了两个步骤:prepare 和 commit:是为了 让两份日志之间的逻辑一致。
如果不是两个阶段提交的话
- 先写 redo log 再写 binlog :进行更新操作将N从0改成1,写入 redo log后,还没有写 bin log 系统就崩了,这样redo log有 **crash-safe ** 的特性,可以将数据回复过来,恢复数据为1,但是此时更新的操作并没有记录到 bin log,这样如果要恢复到某时刻数据的话,N是等于0的
- 先写 bin log 再写 redo log:当将N改成1后,写入了 bin log,系统崩了,此时没有写入 redo log ,恢复过来的话 N是0,但是 bin log记录了将N改成1的操作,恢复到某时刻时会将N改成1 ,数据不一致
小结
redo log 保证了crash -safe,innodb_flush_log_at_trx_commit设置为1 ,表示每个事务的 redo log会写入磁盘,保证mysql重启 redo log数据不丢失
sync_binlog 设置为1,每个事务 binlog 写入磁盘,保证 bin log数据不丢失
redo log 主要用于 数据库崩溃后的数据恢复
bin log 用于 将数据库恢复到每一时刻 使用