MySQL 更新执行的过程
更多内容,前往 IT-BLOG
Select语句的执行过程会经过连接器、分析器、优化器、执行器、存储引擎,同样的 Update语句也会同样走一遍 Select语句的执行过程。

但是和 Select最大不同的是,Update语句会涉及到两个日志的操作 redo log(重做日志) 和 binlog (归档日志)。
那么 Mysql中又是怎么使用 redo log和 binlog?为什么要使用 redo log和 binlog呢?直接执行更新然后存库不就行了吗?还要放在 redo log和 binlog中,这不是多此一举吗?且听我慢慢道来,这里面大有文章。
redo log
大家都是知道 Mysql是关系型数据库,用来存储数据的,在访问数据库量大的时候,Mysql读写磁盘访问的效率是非常低的,加上 sql中的条件对数据的筛选过滤,那么效率就更低了。这也是为什么引入非关系型数据库作为作为数据缓存原因,例如:Redis、MongoDB等,就是为了减少 sql执行期间的数据库 io操作。
同样的道理,若是每次执行 update语句都要进行磁盘 io操作、以及数据的过滤筛选,小量的访问和数据量数据库还可以撑住,那么访问量一大以及数据量一大,这样数据库肯定顶不住。基于上面的问题于是出现了redo log日志,redo log日志也叫做 WAL技术(Write-Ahead Logging),他是一种先写日志,并更新内存,最后再更新磁盘的技术,并且更新磁盘往往是在 Mysql比较闲的时候,这样就大大减轻了 Mysql的压力。
redo log的特点就是:redo log是固定大小,是物理日志,属于 InnoDB引擎的,并且写 redo log是环状写日志的形式:
如上图所示:若是四组的redo log文件,一组为1G的大小,那么四组就是4G的大小,其中 write pos是记录当前的位置,有数据写入当前位置,那么write pos就会边写入边往后移。而 check point是擦除的位置,因为redo log是固定大小,所以当redo log满的时候,也就是 write pos追上 check point的时候,需要清除 redo log的部分数据,清除的数据会被持久化到磁盘中,然后将 check point向前移动。redo log日志实现了即使在数据库出现异常宕机的时候,重启后之前的记录也不会丢失,这就是 crash-safe能力。
binlog
binlog称为归档日志,是逻辑上的日志,它属于 Mysql Server层面的日志,记录着 sql的原始逻辑,主要有两种模式,一个是 statement格式记录的是原始的sql,而 row格式则是记录行内容。那么这样看来 redo log和 binlog虽然记录的形式、内容不同,但是这两者日志都能通过自己记录的内容恢复数据,那么为什么还要这两个日志同时存在呢?只要其中一个不就行了嘛,两个同时存在不就多此一举了嘛。且听我慢慢道来,这里面也大有文章。
因为刚开 Mysql自带的引擎 MyISAM就没有 crash-safe功能的,并且在此之前 Mysql还没有 InnoDB引擎,Mysql自带的 binlog日志只是用来归档日志的,所以 InnoDB引擎也就通过自己 redo log日志来实现 crash-safe功能。
update执行过程
上面说了那么久两种日志的作用和特点,那么这两种日志究竟和 update执行语句有什么关系呢?先来看图:
前提:当前的引擎是使用InnoDB,update语句与 select语句区别主要是这两日志的使用主要是在执行器和引擎之间进行交互时体现的区别。假如执行如下一条简单的更新语句是:
1 update user set age=age+1 where id =2;
上面说过 select语句走过的流程 update语句也会走一遍,当来到执行器的时候:
【1】执行器会调用引擎的读接口,然后找到 id=2的数据行,因为 id是主键索引,索引按照树的搜索找到这一行, 若是数据行已经存在于内存的数据页中就会立即将结果返回,若是不在内存中,就会从磁盘中进行加载到内存中,然后将查询的结果返回。
【2】执行器将返回的结果的age字段+1,并调用引擎的写接口写入更新后的数据行。
【3】引擎获取到更新后的数据行更新到内存和 redo log(也是写入磁盘,顺序写入,比较快)中,并告诉执行器可以随时提交事务,此时的 redo log处于 prepare阶段。
【4】执行器收到引擎的告知后,生成 binlog日志,并且调用引擎的接口提交事务,引擎将 redo log的状态修改为 commit状态,这样这个更新操作算是完成。
两阶段提交
上面详细的说了update语句的执行流程,提到了redo log的 prepare 和 commit两个阶段,这就是两阶段提交,两阶段提交的目的是为了保证 redo log日志与 binlog日志保持数据的一致性。若是 redo log写成功 binlog写失败,或者 redo log写失败 binlog写成功,最后使用这两者日志进行数据恢复得到的结果数据都是不一致性的,所以为了保证两个日志逻辑上的一致,使用两阶段进行提交。
redo log 与 binlog的总结
最后来对比一下这两种日志:redo是物理的,binlog是逻辑的,redo的大小固定,并且以环状的形式写入数据,数据满的时候需要将 redo日志中擦除数据,并且将擦除的数据持久化到磁盘中。而 binlog以追加日志的形式写入,也就是当日志写到一定大小后,就会切换到下一个,并不会覆盖以前写的日志。binlog 是在 Mysql Server层中使用,因为 binlog没有 crash-safe功能,所以 InnoDB引擎自己实现了 redo log日志的 crash-safe的功能,为了保证这两个日志逻辑上的一致使用两阶段提交。在使用 redo和 binlog这两种日志的时候,可以将参数 innodb_flush_log_at_trx_commit和 sync_binlog都设置为1,它表示每次事务提交的时候,都会将日志持久化到磁盘中。
MySQL 更新执行的过程的更多相关文章
- mysql 语句执行的过程
客户端发送一条查询给服务器: 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器段进行SQL解析.预处理,在优化器生成对应的执行计划: mysql根据优化器 ...
- MySQL 语句执行过程详解
MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...
- MySQL更新数据时,日志(redo log、binlog)执行流程
1:背景 项目需要做Es和数据库的同步,而手动在代码中进行数据同步又是Es的一些不必要的数据同步操作和业务逻辑耦合,所以使用的了读取mysql的binlog日志的方式进行同步Es的数据. 问题1:根据 ...
- MySQL查询执行过程
MySQL查询执行路径 1. 客户端发送一条查询给服务器: 2. 服务器先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果.否则进入下一阶段: 3. 服务器端进行SQL解析.预处理,再由优 ...
- mysql系列九、mysql语句执行过程及运行原理(分组查询和关联查询原理)
一.背景介绍 了解一个sql语句的执行过程,了解一部分都做了什么,更有利于对sql进行优化,因为你知道它的每一个连接.where.分组.子查询是怎么运行的,都干了什么,才会知道怎么写是不合理的. 大致 ...
- mysql系列二、mysql内部执行过程
向MySQL发送一个请求的时候,MySQL到底做了什么 客户端发送一条查询给服务器. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器端进行SQL解析.预 ...
- 【大厂面试04期】讲讲一条MySQL更新语句是怎么执行的?
流程图 这是在网上找到的一张流程图,写的比较好,大家可以先看图,然后看详细阅读下面的各个步骤. 执行流程: 1.连接验证及解析 客户端与MySQL Server建立连接,发送语句给MySQL Serv ...
- MySQL InnoDB 事务实现过程相关内容的概述
MySQL事务的实现涉及到redo和undo以及purge,redo是保证事务的原子性和持久性:undo是保证事务的一致性(一致性读和多版本并发控制):purge清理undo表空间背景知识,对于Inn ...
- MySql创建函数与过程,触发器, shell脚本与sql的相互调用。
一:函数 1:创建数据库和表deptartment, mysql> use DBSC; Database changed mysql), ), )); Query OK, rows affect ...
- MySQL性能分析, mysql explain执行计划详解
MySQL性能分析 MySQL性能分析及explain用法的知识是本文我们主要要介绍的内容,接下来就让我们通过一些实际的例子来介绍这一过程,希望能够对您有所帮助. 1.使用explain语句去查看分析 ...
随机推荐
- python爬虫实战——自动下载百度图片(文末附源码)
用Python制作一个下载图片神器 前言 这个想法是怎么来的? 很简单,就是不想一张一张的下载图片,嫌太慢. 在很久很久以前,我比较喜欢收集各种动漫的壁纸,作为一个漫迷,自然是能收集多少就收集多少.小 ...
- shell语法1-概论、注释、变量、字符串
如果感觉有点忘了或者有点懵,敲出来测试测试就好了 一:概论 Linux系统中一般默认使用bash,文件开头需要写#! /bin/bash,指明bash为脚本解释器chmod +x filename:使 ...
- flutter List使用
_tabbarTitile.map((e){ return Tab( text: e, ); }).toList(),
- linux缓冲区溢出尝试
#include <stdio.h>#include <string.h>char Lbuffer[] = "01234567890123456789======== ...
- 圣诞树代码_HTML
这个冬天给TA栽不一样的圣诞树 直接上效果 <!DOCTYPE html> <html lang="en" > <head> <meta ...
- java 递归查子菜单
递归查: @Override public List<PromotionOrgInfoPO> queryOrgInfo() { List<PromotionOrgInfoPO> ...
- Verilog中的时间尺度与延迟
在Verilog的建模中,时间尺度和延迟是非常重要的概念,设置好时间尺度和延迟,可以充分模拟逻辑电路发生的各种情况和事件发生的时间点,来评估数字IC设计的各种要求,达到充分评估和仿真的作用.注意延迟语 ...
- Web_Servlet四大域对象
保存数据的对象作用于从大到小: ServletContext -- 保存数据到web项目中 Session(会话对象) -- Request -- 保存当前请求(链),有转发就保存包括转发的数据 P ...
- Jmeter----Badboy录制
Badboy Badboy安装后出现错误,需要设置 Preferences-->General-->Enable Recording on Startup?的√去掉,play-->S ...
- redis启动报错(TCP backlog setting of 511/overcommit_memory is set to 0/THP)
WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is s ...