一:更新流程

  - 对于更新来说,也同样会根据 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. scala 递归读取文件夹下所有的指定后缀的文件

    def getFile(file:File): Array[File] ={ val files = file.listFiles().filter(! _.isDirectory) .filter( ...

  2. Pyhton3异常处理

    例: while True:        try:            x = int(input("Please enter a number: "))            ...

  3. Hibernate用到HQL查询时的错误

    Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException: student is ...

  4. vue中的父组件传值给子组件

    以上父组件以及父组件里面的代码 下面是子组件以及里面的代码

  5. buoyantSimpleFoam求解器:恒热流壁面【翻译】

    翻译自:CFD-online 帖子地址:http://www.cfd-online.com/Forums/openfoam-solving/148183-buoyantsimplefoam-fixed ...

  6. [Linux] 创建、删除用户

    系统:Ubuntu useradd:创建新用户或更新默认新用户信息 创建新用户 xxx,/home 目录没有同名文件夹,并且此用户没有 shell 权限 $ sudo useradd xxx 创建新用 ...

  7. Mysql --- Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

    我使用的5.5的mysql数据库会报这个错, 换成5.7的就可以了

  8. nginx -- 设置单点登录 sso oidc oauth

    这个开源项目可以找到你想要的: https://github.com/vouch/vouch-proxy

  9. ArcGIS数据建模 (模型构建器modelbuilder) 培训视频 5章28小节587分钟视频 51GIS网站上线

    网址:http://www.51gis.com.cn/kecheng.html?id=358

  10. spring的事务是什么?与数据库的事务是否一样

    spring的事务是什么?与数据库的事务是否一样 先说一下什么是事务,事务:是对数据库的一些列操作. 之前一直觉得事务只针对于数据库当中,5种隔离级别,7种传播行为,后来才发现这是针对Spring的, ...