2 日志系统:一条sql更新语句是如何执行的?
2 日志系统:一条sql更新语句是如何执行的?
前面了解了一个查询语句的执行流程,并介绍了执行过程中涉及的处理模块,一条查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块,最后达到engine。
这里分析一个update语句的流程
mysql> create table T(ID int primary key, c int);
更新语句
mysql> update T set c=c+1 where ID=2;
查询语句的那一套流程,更新语句也是同样会走一遍
执行语句前要先连接db--连接器的工作
在一个表上有更新的时候,跟这个表有关的查询缓存会失效,所以这条语句就会把表T上所有缓存结果都清空--不建议使用查询缓存的原因
接下来,分析器会通过词法和语法分析知道这是一条update语句,优化器决定使用id这个索引,然后执行器负责具体执行,找到这一行,然后update
与查询流程不一样的,更新流程还涉及两个重要的日志模块:redo log和binlog
redo log
在mysql里,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到那条对应的记录,然后再更新,整个过程io成本、查找成本都很高,为了解决这个问题,在mysql里使用WAL,write-ahead loggin,日志先行,关键点就是先写日志、再写磁盘。
当有一条记录需要更新的时候,innodb引擎就会先把记录写到redo log,并更新内存,这个时候更新就算完成了。同时,innodb引擎会在适当的时候,将这个记录更新到磁盘里面。
Innodb的redo log是固定大小,从头开始,写到末尾就又回到开头循环写,有了redo log,innodb就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个功能称为crash-safe。
binlog
从mysql整体来看,一块是server层,主要是mysql功能层面的事情;另一块是引擎层,负责存储相关的具体事宜,redo log就是innodb特有的日志,而server层的日志,就是binlog。
两种日志的不同点
--1 redo log是innodb引擎特有的,binlog是mysql server层实现的,所有引擎都可以使用。
--2 redo log是物理日志,记录的是”在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑。
--3 redo log是循环写的,空间固定;binlog是可以追加写入的,binlog文件写到一定大小后会切换到下一个,并不会覆盖之前的日志
更新update的流程
--1 执行器找到engine取id=2的这一行,id是主键,engine直接用树搜索找到这一行,如果id=2这一行所在的数据本来就在内存中,就直接返回给执行器,否则,需要先从磁盘读入内存,然后再返回。
--2 执行器拿到engine给的行数据,把这个值加上1,比如是n>n+1,得到新的一行数据,在调用引擎接口写入这行新数据
--3 engine将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态,然后告知执行器完成了,随时可以提交事务
--4 执行器生成这个操作的binlog,并把binlog写入磁盘
--5 执行器调用引擎的提交事务接口,engine把刚刚写入的redo log改成提交(commit)状态,更新完成。
两阶段提交
怎样让数据库恢复到7天内任意一秒的状态?
binlog会记录所有的逻辑操作,并且是采用追加写的形式,如果保存了最近一个月的binlog,同时系统有定期的整库备份,当需要恢复到指定的某一秒时,比如某条下午两点发现中午十二点有一次误删表,需要找回数据,可以这么做:
--1 找到最近一次的全备份,如果运气好,可能就是昨晚上的一个备份,从这个备份恢复到临时库
--2 从备份的时间点开始,将备份的binlog依次取出来,重放到中午误删表之前的那个时刻。
这样临时库就跟误删之前的线上一样,然后可以把表数据从临时库取出来,按需要恢复到线上库去。
由于redo log和binlog是两个独立的逻辑,如果不用两阶段提交,要么是先写完redo log再写binlog,或者反过来的顺序,看看有什么问题
--1 先写redo log后写binlog。假设redo log完成,binlog还没有写完,mysql异常重启,由于redo log写完之后,即使系统崩溃,已让能够把数据恢复。
但是由于binlog没写完就crash,这时候binlog没有这条update语句,之后备份日志的时候,存起来的binlog就没有这条语句,如果用binlog恢复的话,就会丢失之前的更新。
--2先写binlog后写redo log。如果在binlog之后carsh,还没来得及写redo log,崩溃恢复后这个update更新就无效,但是binlog里面已经记录了更新,这样用binlog来进行恢复就会导致不一致,同时也会导致备库的不一致。
简单说,redo log和binlog都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。
redo log用于保证crash-safe的能力,innodb_flush_log_at_trx_commit=1表示每次事务的redo log都直接持久化到磁盘,建议设置为1。sync_binlog=1,表示每次事务的binlog都持久化到磁盘,也建议设置为1.--双1模式
2 日志系统:一条sql更新语句是如何执行的?的更多相关文章
- 02 | 日志系统:一条SQL更新语句是如何执行的? 学习记录
<MySQL实战45讲>02 | 日志系统:一条SQL更新语句是如何执行的? 学习记录http://naotu.baidu.com/file/ad320c7a0e031c2d6db7b5a ...
- 一条SQL更新语句是如何执行的
文章首发于公众号「蝉沐风」,认真写好每一篇文章,欢迎大家关注交流 这是图解MySQL的第2篇文章,这篇文章会通过一条SQL更新语句的执行流程让大家清楚地明白: 什么是InnoDB页?缓存页又是什么?为 ...
- 日志系统:一条sql更新语句是如何执行的?--Mysql45讲笔记记录 打卡day2
下面是一个表的创建语句,这个表有一个主键id和一个整型字段c: create table t(id int primary key,c int); 如果要将 id = 2 这一行的值加 1,sql语句 ...
- 02 | 日志系统:一条SQL更新语句是如何执行的?
前面我们系统了解了一个查询语句的执行流程,并介绍了执行过程中涉及的处理模块.相信你还记得,一条查询语句的执行过程一般是经过连接器.分析器.优化器.执行器等功能模块,最后到达存储引擎. 那么,一条更新语 ...
- mysql实战45讲读书笔记(二) 一条SQL更新语句是如何执行的 极客时间
前面我们系统了解了一个查询语句的执行流程,并介绍了执行过程中涉及的处理模块.相信你还记得,一条查询语句的执行过程一般是经过连接器.分析器.优化器.执行器等功能模块,最后到达存储引擎. 那么,一条更新语 ...
- 《Mysql 一条 SQL 更新语句是如何执行的?(Redo log)》
一:更新流程 - 对于更新来说,也同样会根据 SQL 的执行流程进行. - - 连接器 - 连接数据库,具体的不做赘述. - 查询缓存 - 在一个表上有更新的时候,跟这个表有关的查询缓存会失效. - ...
- (转)一条SQL更新语句是如何执行的
名词 MySQL 里经常说到的 WAL 技术,Write-Ahead Logging 第一个日志模块 redo log 也叫日志重写,是InnoDB 引擎特有的日志 - write pos and c ...
- 一文读懂一条 SQL 查询语句是如何执行的
2001 年 MySQL 发布 3.23 版本,自此便开始获得广泛应用,随着不断地升级迭代,至今 MySQL 已经走过了 20 个年头. 为了充分发挥 MySQL 的性能并顺利地使用,就必须正确理解其 ...
- mysql数据库系统学习(一)---一条SQL查询语句是如何执行的?
本文基于----MySQL实战45讲(极客时间----林晓斌 )整理----->https://time.geekbang.org/column/article/68319 一.第一节:一条sq ...
随机推荐
- Node.js 最早 npm 包 request 将被废弃
相信 Node.js 开发者对 Request 都不会陌生,这是一个 Node.js 模块,以 npm 包的形式提供,是一个简单的 HTTP 客户端,通过它可方便地实现 HTTP 请求. 可以看到,r ...
- linux下 设置php的环境变量 php: command not found
在自己的根目录进行运行phpinfo(); 查看php的根目录. 假如自己查询的目录是/www/wdlinux/apache_php-5.6.21/bin, 查询完成后,先进入linux目录查 ...
- 在centOS7.2上编译gcc4.1.2
1.下载安装gcc4.1.2安装包 wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.1.2/gcc-4.1.2.tar.bz2 注:其他版本的安装包可以在上级目录寻找到. ...
- 23_1spring基础
1.spring是什么 2.spring的优势 3.spring体系结构 4.耦合 程序间的依赖关系:类之间的依赖和方法之间的依赖. 解构:降低程序间的依赖关系. 实际开发中应该做到:编译期不依赖,实 ...
- Eureka实现高可用及为Eureka设置登录账号和密码
本文通过两个eureka相互注册实现注册中心的高可用,同时为注册中心配置认证登录. 需要用到的maven配置 <dependency> <groupId>org.springf ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(1)|开篇]
今天我们来开一个新系列. 从零学习rustlang. 简单介绍下rustlang: Rust 是一门系统级编程语言,被设计为保证内存和线程安全,防止段错误产生.作为系统级编程语言,它的基本理念是 “零 ...
- 跨域 (1) jsonp 跨域
jsonp 的例子 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- Lambda学习总结(一)--函数式接口
Lambda 表达式是 JDK 1.8 里面的一个重要更新,这意味着 Java 也开始承认了函数式编程,并且尝试引入其中,我们今天就来了解下它的使用. 一.函数式接口 1.1 概念 函数式接口在 Ja ...
- 前端每日实战:158# 视频演示如何用纯 CSS 创作一个雨伞 toggle 控件
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/pxLbjv 可交互视频 此视频是可 ...
- mysql——二级索引(辅助索引)
二级索引:叶子节点中存储主键值,每次查找数据时,根据索引找到叶子节点中的主键值,根据主键值再到聚簇索引中得到完整的一行记录. 问题: 1.相比于叶子节点中存储行指针,二级索引存储主键值会占用更多的空间 ...