一:更新流程

  - 对于更新来说,也同样会根据 SQL 的执行流程进行。

    - 

  - 连接器

    - 连接数据库,具体的不做赘述。

  - 查询缓存

    - 在一个表上有更新的时候,跟这个表有关的查询缓存会失效。

    - 这也就是我们一般不建议使用查询缓存的原因。

  - 分析器

    - 接下来,分析器会通过词法和语法解析知道这是一条更新语句。

  - 优化器

    - 优化器决定要使用 ID 这个索引。

  - 执行器

    - 然后,执行器负责具体执行,找到这一行,然后更新。

  - PS

    - 与查询流程不一样的是,更新流程还涉及两个重要的日志模块,它们正是我们今天要讨论的主角:

    - redo log(重做日志)和 binlog(归档日志)。

二: redo log

  - Mysql 更新存在的问题

    - 在 MySQL 中,如果每一条更新记录,都需要写入磁盘。

    - 然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。

    - 为了解决这个问题,MySQL 的设计者就用了 redo log 的概念来解决这个问题。

  - redo log 概述

    - redo log 是 InnoDB 独有的,属于 存储引擎层的

  - redo log 工作流程

    - 具体来说,当有一条记录更新的时候,InnoDB 引擎就会先把记录写到 redo log 里面,并更新内存,这个时候更新就算完成了。

    - 同时,InnoDB 会在适当的时候,将这个操作记录更新到磁盘里面.

    - PS

      - InnoDB 的 redo log 是固定大小的

        - 比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么总共就可以记录 4GB 的操作。

        - 从头开始写,写到末尾就又回到开头循环写

      - 当 redo log 被写满时候,这时候不能在执行新的更新,必须停下来,擦除一些 redo log 的日志,写入磁盘

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

三 :binlog

  - binlog 概述

    - binlog(归档日志) 是 Server 层特有的

  - 为什么会有两份日志?

    - 因为最开始 MySQL 里并没有 InnoDB 引擎。

    - MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。

    - 而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的

    - 所以 InnoDB 使用另外一套日志系统-- 就是 redo log 来实现 crash-safe 能力。

四 :binlog 和 redo log 的不同

  - redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。

  - redo log 是物理日志,记录的是“在某个数据页上做了什么修改”

  - binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。

  - redo log 是循环写的,空间固定会用完;

  - binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

五:再看 Update 执行过程

  - 例如

    - mysql> update T set c=c+1 where ID=2;

  - 流程

    - 执行器先找引擎取 ID=2 这一行。

      - ID 是主键,引擎直接用树搜索找到这一行。

      - 如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器

      - 否则,需要先从磁盘读入内存,然后再返回。

    - 执行器拿到引擎给的行数据

      - 把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。

    - 引擎将这行新数据更新到内存中

      - 同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。

      - 然后告知执行器执行完成了,随时可以提交事务。

    - 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。

    - 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

    - 

六:redo 的 “两阶段提交”

  - 根据上面的流程图,可以看到,redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。

  - 原因

    - 由于 redo log 和 binlog 是两个独立的逻辑

      - 如果不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者采用反过来的顺序,会导致数据的不一致出现。

    - 简单说,redo log 和 binlog 都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。

  

  - 举例一个完整的交易流程

    - 账本记上 卖一瓶可乐(redo log为 prepare状态),然后收钱放入钱箱(bin log记录)然后回过头在账本上打个勾(redo log置为commit)表示一笔交易结束。

    - 如果收钱时交易被打断,回过头来整理此次交易,发现只有记账没有收钱,则交易失败,删掉账本上的记录(回滚)

    - 如果收了钱后被终止,然后回过头发现账本有记录(prepare)而且钱箱有本次收入(bin log),则继续完善账本(commit),本次交易有效。

七:小结

  - redo log 用于保证 crash-safe 能力。

    - innodb_flush_log_at_trx_commit 这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘。

    - 这个参数建议设置成 1,这样可以保证 MySQL 异常重启之后数据不丢失。

  - sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。

    - 这个参数也建议设置成 1,这样可以保证 MySQL 异常重启之后 binlog 不丢失。

  - 还介绍了与 MySQL 日志系统密切相关的“两阶段提交”。

    - 两阶段提交是跨系统维持数据逻辑一致性时常用的一个方案,即使你不做数据库内核开发,日常开发中也有可能会用到。

《Mysql 一条 SQL 更新语句是如何执行的?(Redo log)》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. TCP四次握手断开连接

    建立连接非常重要,它是数据正确传输的前提:断开连接同样重要,它让计算机释放不再使用的资源.如果连接不能正常断开,不仅会造成数据传输错误,还会导致套接字不能关闭,持续占用资源,如果并发量高,服务器压力堪 ...

  2. mysql IFNULL函数和COALESCE函数使用技巧

    IFNULL() 函数      IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL 则返回第一个参数的值. IFNULL() 函数 ...

  3. 由Java正则表达式的灾难性回溯引发的高CPU异常:java.util.regex.Pattern$Loop.match

    问题与分析 某天领导report了一个问题:线上的CPU自从上一个版本迭代后就一直处于居高不下的状况,领导看着这段时间的曲线图判断是有两条线程在不停的死循环. 接到任务后去查看了AWS的CloudWa ...

  4. Tkinter 之ListBox列表标签

    一.参数说明 参数 作用 background (bg) 设置背景颜色 borderwidth (bd) 指定 Listbox 的边框宽度,通常是 2 像素 cursor  指定当鼠标在 Listbo ...

  5. linux搭建代理服务器+蚁剑配置客户端代理

    一:linux搭建代理服务器 0x00 介绍 关于搭建代理服务器的方法,我也是刚刚接触,从网上找了一些能够行得通的方法来给大家做个分享: 这里我用的是Tinyproxy作为代理服务软件.这个东西很小, ...

  6. 20175313 张黎仙《获奖感想与Java阶段性学习总结》

    一.获奖感想 很荣幸能够成为为数不多的小黄衫获得者之一,这是对我近一学期以来学习成果的肯定,也激励着我更加努力学习. 首先我要感谢的人就是娄嘉鹏老师.我曾在师生关系中提到,我认为的好老师的特点之一是: ...

  7. 2018-2019-2 20165312《网络攻防技术》Exp 8 Web基础

    2018-2019-2 20165312<网络攻防技术>Exp 8 Web基础 目录 一.相关知识点总结 二.实验内容 三.实验步骤 四.实验总结及问题回答 五.实验中遇到的问题及解决方法 ...

  8. qt Qt5开发

    本章将介绍使用Qt5开发.我们将告诉你如何安装Qt SDK,如何使用Qt Creator IDE创建以及运行一个简单的Hello World应用程序. 一.安装Qt5 SDK Qt SDK包括构建桌面 ...

  9. git 初次提交

    前提:已经关联了ssh到本地,不用再输入用户名和密码 知道仓库地址:https://xxx.xxx.com/aiotcloud/yihao01-node-js.git 第一步:进入本地文件夹执行 gi ...

  10. Drawable: getIntrinsicWidth()和getIntrinsicHeight()方法的使用误区

    经常会使用上述两个API来获取ImageView中显示图片的大小,但是在某些情况下,这两个API返回的大小可能与原图的大小不一致,比如原图大小是72*72,分别把原图放置在xhdpi,xxhdpi,x ...