专栏首页洁癖是一只狗一条更新语句如何执行

一条更新语句如何执行

一条更新语句如何执行呢,他和查询语句一样吗,我们先看一张图

其实更新语句和查询语句的流程是基本一样的,但是他其中不一样的是涉及两个日志模块,也就是我们经常提到的redo log(重做日志)和binlog(归档日志)。

往往我们在开发的日常中,DBA同事经常在我们不小心误删除了某些数据,DBA同事总能帮我们找回来,其实他们也是利用这两个日志。

redo log

我们现在回忆一下以前酒馆的记账的模式,酒馆里有一个黑板,当酒店人多的时候,掌柜的就会把账临时记录在黑板上,当人少的时候在把账目记录在账本上,当然也可以直接把账目记录在账本上,但是这样就比较麻烦,还要在账本上找到对应的记录,再去修改记录。显然易见我们利用黑板效率更高一点,这里的黑板相当于我们数据库的redo log。

上面说的黑板和账本的配合就是我们常说的WAL(WriteAhead Logging)技术,先写日志,在写入磁盘.

具体来说,当我们要更新一条记录的时候,我们先把他写入redo log中,并更新内存,当InnoDb适当的时候把这个操作放到磁盘中,正如酒店空闲的时候把黑板的账目记录在账本上。

但是往往酒店的黑板是固定大小的,黑板写满了,我就不得把记录写到账本上,然后腾出新的空间,我们的redo log也是一样的,也是有有固定大小的,比如我们可以配置4个文件,每一个文件可以放置4G大小的数据,重头开始写,循环写,正如下图

check_point记录我们擦除的位置,write_pos记录我们写到的位置,一边写一边向后移动,当check_point和write_pos重合的时候,我就得把check_point向后移动。

因此有了redo log,当数据库发生异常重启,我们也能保证之前提交的记录不会丢失,当然我们理解一个概念crash-safe,就如账面酒店关门歇业几天,当开业的时候,依然可以通过账目和黑板明确账目.

binlog

我们之前看过数据库分为两个模块,存储引擎和server,上面说到的redo log日志是InnnoDB的特有日志,而server也有自己的日志,他就是binlog日志

当然我们会想到为什么有了binglog日志,还要有redo log,那是因为binglog日志是归档的作用,没有crash-safe的能力,因此使用插件的形式引入了redo log,

他们的不同点

redo log 是物理日志,记录在数据库做了什么,binlog日志是逻辑日志,记录了语句的原始逻辑

redo log是InnoDB存储引擎独有的,binglog是在server层,所有存储引擎都可以使用,

redo log是循环使用的,binLog日志是追加的

一条更新语句整体的执行流程如下

update T set c=c+1 where id =2
  1. 执行器先获取Id=2,id是主键,利用树索引找到这一行,这条数据刚好在内存中,直接返回,如果没在,执行器到磁盘读取,更新到内存,然后在返回
  2. 执行器获取到这条数据之后,更新c的值,然后把调用引擎的接口写入
  3. 引擎把这条数据更新到内存中,然后记录在redo log中,此时redo log状态为prepare,此时告诉引擎,随时可以提交事务
  4. 执行器生成这动作的binlog,并写入磁盘
  5. 执行器执行引擎的事务接口,提交事物,redo log的状态改成提交状态(commit),更新完成

我们很多人疑惑为什么redo log开始的状态prepare状态,当提交完事务在改成commit,也就是我们常说的二阶段提交。

二阶段提交

为什么要使用二阶段提交呢,是为了保持两份日志的一致性,我们先回顾一下数据库如何恢复数据,我们知道binlog日志是追加的形式,我们每年或每天都会进行备份,当我需要恢复数据的时候,如下操作

  1. 拿到最近一次的备份,从这个备份恢复到临时库中
  2. 然后从这个备份时间点,开始把binlog的日志恢复到有问题的时间点

这个时候就和误删出之前的数据一样了,这样可以在把需要的数据放到数据库中.

我们再来说为什么要使用二阶段提交,不如使用反证法证明一下

如果不用二阶段提交,一个日志写完,在写第二个日志,当第二个日志,没有写入,就直接crash宕机了。会有什么结果

先写redo日志,在写binlog日志,当redo写完之后,binlog没有来的及写入,此时宕机,我们之前就说过,crash之后,我们依然可以恢复到1(c+1)之后的数据

但是,binlog的这条更新记录没有写入,因此之后的备份,就会少这样的逻辑,如果要使用这个binlog日志恢复临时库的时候,数据还是之前的数据c=0的的数据,会导致与源库不一致

先写binlog,在写入redo日志,当redo还没有写入之后,宕机了,此时redo 日志还是c=0的状态,但是当binlog使用的时候,恢复出多了一个事物,就会导致与源库的不一致。

可以看出不适用二阶段提交,会导致用日志恢复出的数据库和源库不一致,当然你可能任务宕机的概率很低,其实当你需要扩容的时候,也会用到日志搭建从库,这样备份出的数据库会和主库的状态不一致.

简单来说,redo log和 binlog都可以表示事物的状态,而二阶段提交保证了两个日志的状态保持一致。

最后,我们可以设置innodb_flush_log_at_trx_commit为1,保证每次事务的redolog都持久化磁盘,保证redolog的crash-safe,保证数据不会丢失,也可以设置sync_binlog设置为1,这样保证了数据库重启之后保证binlog不会丢失.

希望此文对大家有所帮助,也希望大家持续关注转载。

本文分享自微信公众号 - 洁癖是一只狗(rookie-dog),作者:洁癖汪

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Zookeeper基础篇---面试Paxos算法

    Paxos算法是一种基于消息传递的具有高容错性的一致性算法,Paxos算法是一种公认的晦涩难懂的算法,并且实现它有很大难度。比较有名的工程是实现有Google ...

    小土豆Yuki
  • Mysql进阶篇--一条sql查询语句如何执行

    日常中,我们只看到返回一条或多条结果,并没有过多的去关注查询语句具体要执行那些流程,今天我们看看他的执行流程,我们先整体的看一下他的流程图,如下

    小土豆Yuki
  • Docker 容器化部署实践Docker Compose

    Docker compose是docker提供的一个命令行工具,实现对Docker容器集群的快速编排。

    小土豆Yuki
  • 必须了解的mysql三大日志-binlog、redo log和undo log

    来自:https://juejin.im/post/6860252224930070536

    用户6543014
  • Silverlgiht:快速去除/恢复对象的颜色

    某些场景下,想将一个对象快速隐藏、恢复,而且不影响布局。有一种方法:将对象的透明度在1与0之间切换。 问:为什么不用Visibility? 答:这通常会导致重...

    菩提树下的杨过
  • 机器学习不是万能的!谷歌工程师:激发人的想象力才能创造惊艳的用户体验

    大数据文摘
  • 2:0!Dota2世界冠军OG被OpenAI碾压,全程人类只推掉两座外塔

    AI向Dota界卷土重来,一下子把Dota 2世界冠军打得落花流水,在刚刚结束的三局两胜比赛中轻松获胜。

    量子位
  • 产业互联网:构建智能+时代数字生态新图景 | 重磅发布(附全文下载)

    3月29日下午,“2019腾讯全球数字生态大会新闻发布会”在京举行,腾讯云联合腾讯研究院,共同发布了行业重磅报告:《产业互联网——构建智能+时代数字生态新图景...

    腾讯大讲堂
  • 7 Papers | 2019安卓手机AI性能评测;谷歌T5预训练模型刷榜GLUE;自动驾驶论文综述

    论文 1:AI Benchmark: All About Deep Learning on Smartphones in 2019

    机器之心
  • pip install browserc

    这几天在看《精通Scrapy网络爬虫》一书,需要涉及到browsercookie库的安装。一切有些不如人意,花了两三个小时才安装成功,所以在这里记录一下,一方面...

    py3study

扫码关注云+社区

领取腾讯云代金券