MySQL 更新语句的执行流程

MySQL 更新语句的执行流程

一、基本流程:

查询语句的流程,更新语句也会同样的走一遍。

  1. 在一个表有更新的时候,查询缓存会失效;
  2. 接下来分析器会通过词法分析语法,分析这是一条更新语句;
  3. 优化器决定使用ID这个索引;
  4. 执行器负责更新,找到这一行,然后进行更新;

与查询流程不同的是,更新流程涉及两个重要日志模块。

二、redo log(重做日志):

redo log 是InnoDB引擎特有的日志

在MySQL中,每次的更新操作都需要写进磁盘,然后磁盘也要找到对应记录,进行更新,整个过程的IO成本、查找成本都很高。可使WAL(Write-Ahead-Logging)技术,先写日志,再写磁盘

InnoDB 引擎先把记录写到redo log 里,并更新内存,这时更新完成。同时InnoDB引擎在适当的时候,将这个操作记录更新到磁盘里。

InnoDB的redo log 是固定大小,若可配置一组4个文件,每个文件的大小是1GB,总共记录就是4GB;
在这里插入图片描述

  • write pos 是当前记录的位置,checkpoint 是当前要擦除的位置,都是往后推,并且循环,擦除记录前要把记录更新到数据文件;

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

    innodb_flush_log_at_trx_commit 这个参数设置成1时,每次事务redo log 都直接持久化到磁盘中,保证MySQL异常重启后数据不丢失;

三、binlog (归档日志):

MySQL服务层也有自己的日志,所有引擎都可以使用,称为binlog。

sync_binlog 这个参数设置成1时,每次事务binlog都持久化到磁盘,这个参数建议设置成1,保证MySQL异常重启后 binlog不丢失;

1.Binlog 的两种模式:

statement 格式,记SQL语句;

row格式,会记录行的内容;

更新前、后都会进行记录

四、两种日志的区别:

  1. redo log 是InnoDB 引擎特有的;binlog 是MySQL服务层实现的,所有引擎都可使用;
  2. redo log 是物理日志,binlog 是逻辑日志;
  3. redo log 是循环写入,空间固定会用完,binlog是追加写入;

五、执行器和InnoDB引擎执行update语句流程:

update T set c=c+1 where ID = 2;

在这里插入图片描述

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

浅色:InnoDB内部执行

深色:在执行器中执行

1.为什么会有两阶段提交?

  1. 为了让两份日志之间逻辑一致。由于redo log 和 binlog是两个独立的逻辑,如果不用两阶段提交,那么就是先写完redo log,再写binlog;
  2. redo log 和 binlog 都可用于表示事务提交状态,两个阶段提交就是让两个状态保持逻辑一致;

2.redo log 和 binlog是怎么关联起来的?

它们有一个共同的数据字段,叫XID。崩溃恢复的时候,会按顺序扫描redo log;

  • 如果碰到既有prepare,又有commit的redo log,就直接提交;
  • 如果碰到只有prepare、而没有commit的redo log,就拿着XID 去binlog 找对应的事务;
发布了147 篇原创文章 · 获赞 170 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Fe_cow/article/details/103052268