0
点赞
收藏
分享

微信扫一扫

Mysql 45讲学习笔记(二)SQL更新语句的执行


一.日志模块:redo log

存在问题:

  • 每一次的更新操作都需要写进磁盘,然后磁盘找到对应的那条记录,然后再更新,整个过程IO成本,查找成本很高。

解决方案:

WAL技术,Write-Ahead Logging 

  • 先写日志,再写磁盘  ----与Redis正相反

二.WAL技术

  • 当有一条记录需要更新的时候,InnoDB引擎会先把记录写道redo log里面再更新内存,这时候就算更新完成。
  • InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,这个更新往往会在系统空闲时进行。

三. redo log

InnoDB的red log是固定的,可以配置为一组4个文件,每个文件的大小是1GB

Mysql 45讲学习笔记(二)SQL更新语句的执行_sql

InnoDB可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力被称为crash-safe

四.日志模块:binlog

  • Server层的日志-binlog(归档日志)
  • 引擎层,负责存储相应的具体事宜,innoDB日志-redo log

两者不同点:

  • redo log是InnoDb引擎特有的;binlog是MySQL的server层实现的,所有引擎都可以使用。
  • redo log是物理日志,记录的是“在某个数据页上做了什么修改”,binlog是逻辑日志,记录执行语句
  • redo log是循环写,空间固定会用完;binlog是可以追加写,指binlog文件会一直追加,不会覆盖之前的日志。

五.执行update语句时的内部流程

  1. 执行器先找引擎ID=2这一行。ID是主键,引擎直接用树搜索找到这行 ,如果ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器,否则从磁盘读入内存再返回。
  2. 执行器拿到引擎行数据,值加一,再调用引擎接口写入
  3. 引擎将这行新数据更新至内存中,同时这个更新操作记录到redo log中,此时redo log处于prepare状态,然后告知执行器完成,可以提交事务。
  4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎刚把写入的redo log改成提交(commit)状态,更新完成。

Mysql 45讲学习笔记(二)SQL更新语句的执行_sql_02

六.两阶段提交

  • 为什么必须要两阶段提交?
  • 让两份日志之间的逻辑一致

 怎样让数据库恢复到半个月内任意一秒的状态

    解决方案:

  • binlog会记录所有的逻辑操作,并且采用"追加写"的形式
  • 备份系统可以保存最近半个月的所有binlog,同时系统会定期做整库备份
  • 这个定期可以取决于系统的重要性,可以一天一备份,也可以一周一备份。

恢复场景:某天下午两点发现中午十二点有一次误删表

  • 找最近一次全量备份,恢复到临时库;
  • 从备份的时间点开始,将备份的binlog依次取出来,重新放到中午误删表之前那个时刻。
  • 表数据从临时库取出来,按需要恢复到线上库去。

不做两提交的缺点:

先写 redo log 后写 binlog 

  • 假设redo log写完,binlog写之前,musql崩溃
  • redo log写完以后,系统崩溃,让能把数据恢复过来
  • binlog没写完就crash了,这时候binlog没有记录这个语句。
  • 但是通过binlog同步的从库会导致从库缺失命令。

先写binlog再写redo log

  • binlog写完以后crash住,但是redo log还没写,这时候事务无效
  • 但是binlog日志已经记录
  • 那么通过binlog同步的从库会导致从库增加了这个命令的执行。
  • redo log用于保证crash-safe能力
  • innodb_flush_log_at_trx_commit 为1 保证每次事务的redo_log都直接持久化到磁盘,mysql重启之后数据不丢失。
  • sync_binlog这个参数设置成1的时候,表示每次事务的binlog都会持久化到磁盘保证mysql异常重启之后binlog不丢失。
举报

相关推荐

0 条评论