02 | 日志系统:一条SQL更新语句是如何执行的?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangqi1991410/article/details/84751294

#<-- 该文章借鉴林晓斌老师mysql实战45讲 ->

一条SQL更新语句是如何执行的?

  1. 更新是建立在查询之上的,可以说更新==查询+修改,所以更新操作也会走一遍查询语句的流程.

  2. mysql的更新操作涉及到两个重要日志文件:redo log(重做日志)和 binlog(归档日志):
    a. redo log 是属于innodb引擎的,myisam引擎不存在redo log 所以这也是为啥innodb拥有事务功能,而myisam没有! 当一条记录需要更新的时候,innodb引擎会先把记录写到redo log中,并更新内存,这个时候对客户端来说更新操作就算是完成了,innodb引擎会在系统空闲的时候将redo log中的操作更新到磁盘中
    (注意:虽然redo log 和 bin log,为了快速响应SQL充当了粉板,不过它们本身也是文件,在进行日志记录的时候也需要读写磁盘不过日志文件是顺序写,不需要寻址,而更新数据需要寻址,所以写日志效率更高)

    b. redo log 的文件个数和大小是可以配置的,并且内存空间可以循环利用,存在于data目录中,以ib_logfile[number]方式命名,例如 ib_logfile[0]

    c. binlog属于服务层,只能用于归档,binlog是二进制格式,形式为mysql-bin.000001, mysql-bin.000001 等

  3. 两种日志的比较:
    a. redo log 是innodb特有的,二binlog属于Server层,所有引擎都可以使用

    b. redo log是物理日志,记录的是“在某个数据页上做了什么修改”,有了redo log 即使数据库异常重启,之前提交的数据也不会丢失,这个能力成为crash-safe;binlog是逻辑日志,记录的是这个语句的原始逻辑 ,假如你需要将数据库恢复到一周前的状态就需要用到binlog了 ;binlog有两种模式,statement 格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后都有;

    c. redo log是循环写的,例如配置redo log 数量为两个大小为1G,当第二个写完的时候innodb引擎会将第一个日志文件部门空间的日志写入磁盘并擦除,以供循环使用
    在这里插入图片描述

  4. update student set name=‘zhangqi’ where id=2的执行流程:

    a. 执行器先找存储引擎取id为2的记录. 如果id=2的记录所存在的数据页刚好在内存中,则直接返回给执行器,否则需要从磁盘将记录加载到内存再返回给执行器;

    b. 执行器拿到这条记录后将name改为‘zhangqi’,得到一条新的记录,然后再将新得到的记录返回给引擎;

    c. 引擎将得到的记录更新到内存中,并写入redo log中(写入磁盘),此时redo log处于perpare状态,引擎将此状态通知给执行器;

    d. 执行器接收引擎通知的perpare状态后,生成更新操作的binlog,并写入磁盘,然后再调取引擎的提交事务接口;

    e. 引擎将redo log 改为commit状态,写入磁盘,更新完成

    f. 下图为SQL update T set c=c+1 where ID=2; 的执行流程,其中深色框在执行器中执行,浅色则在引擎中.
    在这里插入图片描述

  5. 为啥redo log 分两阶段提交?
    目的:确保redo log 和 binlog保持逻辑上的一致
    假如你最近的一次数据库全量备份是一周前,假如你现在需要恢复到三天前的状态

    a. 先写binlog,后写redo log。也就是说更新语句写完binlog的时候,数据库异常重启,这个时候数据库中 id 为2 的记录name值并没有改为 ‘zhangqi’,当你需要恢复到 三天前的状态时需要用到binlog,这个时候就会将 id为2的记录name值改为 ‘zhangqi’, 而我们知道实际并没有修改.

    b. 先写redo log,后写binlog。 也就是说更新语句写完redo log的时候,数据库异常重启,这个时候数据库中 id 为2 的记录name值已经改为 ‘zhangqi’,当你需要恢复到三天前的状态时需要用到binlog,这个时候id为2的记录name值并没有改为 ‘zhangqi’, 而我们知道实际上已经修改.

    c. 总结:当数据库需要还原之前某一个状态的时候,需要确保redo log 和 binlog 保持逻辑上的一致.

    d. redo log 和 bin log 通过事务ID进行对应

  6. Binlog如果已经接受,那么redolog是prepare, binlog已经完整了对吧,这时候崩溃恢复过程会认可这个事务,提交掉。

  7. Redo log不是记录数据页“更新之后的状态”,而是记录这个页 “做了什么改动”。
    Binlog有两种模式,statement 格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后都有。

猜你喜欢

转载自blog.csdn.net/zhangqi1991410/article/details/84751294