• redo log和bin log


    讲redolog和binlog之前,先要讲一下一条mysql语句的执行过程。

    1、client的写请求到达连接器,连接器负责管理连接、验证权限;

    2、然后是分析器,负责复习语法,如果这条语句有执行过,在缓存内,那么就从缓存去写;

    3、缓存没有的话,那就到了优化器部分。负责优化sql读写,选择索引;

    4、接下来是执行器,负责操作引擎,并返回结果。

    接下来就要进入正题,说一下第四步是如何执行的。

    redo log

    与查询不一样的是,更新流程还涉及两个重要的日志模块,它们正是我们今天要讨论的主角:redo log(重做日志)和bin log(归档日志)。

    innodb的更新操作不是直接写入磁盘的,而是先记录日志,也就是redo log,然后等到db没那么忙碌的时候刷到磁盘上。这样保证了mysql的高效写操作。为什么会这么设计呢?因为每次更新操作先要查询,这里有磁盘io,查到后修改数据,刷入磁盘,又是一次io,每次都这样做的话会非常慢,所以就先记录在内存中,然后记录在redo-log中,然后按照策略刷入磁盘。这个技术叫做WAL技术。因为如果只记录在内存中的话,mysql崩溃会导致改动的数据丢失。所以redo log保证了innodb的crash-safe。(注意:mysql是没有redo log的,它是innodb特有的。不过现在mysql大部分情况下都会选用innnodb。)mysql crash后,故障恢复会从redo log中读取数据。

    不过redo log是有大小限制的,比如设置了4个1G的redo log,那么第3个写满的时候会覆盖第0个的log文件。

    bin log

    redo log是在存储引擎层面的日志,负责存储和crash恢复。bin log 是server层的日志。

    为什么会有两份日志呢?

    因为只依靠bin log是没有crash safe能力的。而且redo log是有大小限制的。

    redo log和bin log主要有如下几个区别:

    1、所属层不一样,bin log是server层,redo log是存储层的日志,只有innodb才有。

    2、redo log有大小限制,是循环写的,而binlog没有这样的限制;

    3、redo log是物理日志,记录的是“在某个数据页上做了什么修改”,bin log是逻辑日志,记录的是语句的原始逻辑,比如给id=3的这一行的count做加一操作。

    接下来看一下一条update语句的执行过程:

    1、首先查到这一行或者多行数据;

    2、然后修改数据,写入内存,并将修改写入redo log,此时redo log处于prepare阶段,并告诉执行器可以提交了;

    3、返回ok给server的执行器,执行器收到ok后在binlog中记录原始语句,写入磁盘;

    4、binlog记录完成后,执行器告诉引擎层,引擎层将对应的redo log从prepare状态改成commit状态。

    这就是2PC。

    如果我们要将数据库恢复到某一个时刻点,比如本周二,那么找到周二前最近的全量备份,然后执行备份时间到本周二的binlog,得到一个临时的数据库。

    可不可以不要做两阶段提交,而改成把这两步操作独立做呢?可以考虑一下如下两个场景(把某一行的count列从0改成1):

    1、先做redo log,后写bin log

    如果先写redo log成功后,还没写binlog就崩了,此时count列已经变为1,而数据恢复时,用的是bin log,bin log里少了这一个操作,那么就出现用bin log恢复出来的db和当前的db比,出现了不一致。

    2、如果先做bin log,然后写redo log

    如果写完bin log后,redo log还没写,就崩了,也就是说崩溃时的db是没有count=1这个修改的。而用bin log恢复出来的db里是有这行记录的,那么也出现了不一致。

    所以,update时针对redo log和bin log做2PC还是很有必要的。

    此外。redo log有个配置项innodb_flush_log_at_trx_commit设置成1,保证每次事务后时redo log都能更新到磁盘。这样就不会出现丢失的现象。

    innodb_flush_log_at_trx_commit=0表示每秒写入磁盘。这样有可能最多丢失1秒钟的数据。

    设置为2时,表示每次事务后将redo log的缓存写入os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk。这样的话,如果系统崩了会丢失一秒的数据,如果mysql崩了,则不会丢失数据。

    sync_binlog也建议设置成1,表示每次事务后的binlog会持久化到磁盘,这样可以保证mysql异常重启后的binlog不会丢失记录。

    最有有个问题,写日志也是写磁盘,直接更新数据也是写磁盘,都是写磁盘,效率不是一样的吗?这样innodb的redo log不是多此一举吗?因为redo log是追加的形式写磁盘,所以效率很高,而修改数据库的数据是随即写,效率就低了很多。

  • 相关阅读:
    华为交换机配置命令总结
    Linux 系统启动项修复
    Linux菜鸟成长日记 ( Linux 下的 ftp 文件传输协议 )
    Linux 查看用户命令
    linux 查看过滤命令命令
    Linux篇---ftp服务器的搭建
    linux挂载详解
    园区IP地址规划(非常详细)
    Linux创建、删除文件和文件夹命令
    CentOs 7 安装 Xampp
  • 原文地址:https://www.cnblogs.com/howo/p/11531157.html
Copyright © 2020-2023  润新知