MySQL存储引擎如何完成一条更新语句的执行!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL存储引擎如何完成一条更新语句的执行!

假设我们有一条SQL语句是这样的:

update t_user set name='月伴飞鱼' where id=1;

那么我们先想一下这条SQL语句是如何执行的?

首先肯定是我们的系统通过一个数据库连接发送到了MySQL上,然后肯定会经过SQL接口、解析器、优化器、执行器几个环节,解析SQL语句,生成执行计划,接着去由执行器负责这个计划的执行,调用InnoDB存储引擎的接口去执行。

大致会走下图的这个流程

我们就来探索一下这个存储引擎里的架构设计,以及如何基于存储引擎完成一条更新语句的执行

缓冲池

InnoDB存储引擎中有一个非常重要的放在内存里的组件,就是缓冲池(Buffer Pool),这里面会缓存很多的数据, 以便于以后在查询的时候,万一你要是内存缓冲池里有数据,就可以不用去查磁盘了

所以当我们的InnoDB存储 引擎要执行更新语句的时候 ,比如对“id=1”这一行数据,他其实会先将“id=1”这一行数据看看是否在缓冲池里,如果不在的 话,那么会直接从磁盘里加载到缓冲池里来,而且接着还会对这行记录加独占锁。

因为我们想一下,在我们更新“id=1”这一行数据的时候,肯定是不允许别人同时更新的,所以必须要对这行记录加 独占锁

undo日志文件

如何让你更新的数据可以回滚?

接着下一步,假设“id=1”这行数据的name原来是“周星星”,现在我们要更新为“月伴飞鱼”,那么此时我们得先 把要更新的原来的值“周星星”和“id=1”这些信息,写入到undo日志文件中去。

数据库中,如果我们执行一个更新语句,要是他是在一个事务里的话,那么事 务提交之前我们都是可以对数据进行回滚的,也就是把你更新为“月伴飞鱼”的值回滚到之前的“周星星”去。

所以为了考虑到未来可能要回滚数据的需要,这里会把你更新前的值写入undo日志文件,我们看下图。

更新buffer pool中的缓存数据

这里所谓的更新内存缓冲池里的数据,意思就是把内存里的“id=1”这行数据的name字段修改为“月伴飞鱼”

当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时对他加锁之后,而且还把更新前的旧值写入undo日志文件 之后,我们就可以正式开始更新这行记录了,更新的时候,先是会更新缓冲池中的记录,此时这个数据就是脏数据 了。

那么为什么说此时这行数据就是脏数据了呢?

因为这个时候磁盘上“id=1”这行数据的name字段还是“周星星”,但是内存里这行数据已经被修改了,所以 就会叫他是脏数据。

redo log

接着我们来思考一个问题,按照上图的说明,现在已经把内存里的数据进行了修改,但是磁盘上的数据还没修改

那么此时万一MySQL所在的机器宕机了,必然会导致内存里修改过的数据丢失,这可怎么办呢?这个时候,就必须要把对内存所做的修改写入到一个Redo Log Buffer里去,这也是内存里的一个缓冲区,是用来存 放redo日志的

所谓的redo日志,就是记录下来你对数据做了什么修改,比如对“id=1这行记录修改了name字段的值为“月伴飞鱼”,这 就是一个日志。我们先看下图

这个redo日志其实是用来在MySQL突然宕机的时候,用来恢复你更新过的数据的

提交事务的时候将redo日志写入磁盘中

接着我们想要提交一个事务了,此时就会根据一定的策略把redo日志从redo log buffer里刷入到磁盘文件里去。

此时这个策略是通过innodb_flush_log_at_trx_commit来配置的,他有几个选项。当这个参数的值为0的时候,那么你提交事务的时候,不会把redo  log buffer里的数据刷入磁盘文件的,此时可能你都  提交事务了,结果mysql宕机了,然后此时内存里的数据全部丢失。相当于你提交事务成功了,但是由于MySQL突然宕机,导致内存中的数据和redo日志都丢失了

当这个参数的值为1的时候,你提交事务的时候,就必须把redo log从内存刷入到磁盘文件里去,只要事务提交成功,那么redo log就 必然在磁盘里了

那么只要提交事务成功之后,redo日志一定在磁盘文件里,此时你肯定会有一条redo日志说了,“我此时对哪个数据做了一个什么修 改,比如name字段修改为月伴飞鱼了”。

然后哪怕此时buffer pool中更新过的数据还没刷新到磁盘里去,此时内存里的数据是已经更新过的“name=月伴飞鱼”,然后磁盘上的数 据还是没更新过的“name=周星星”。

此时如果说提交事务后处于上图的状态,然后mysql系统突然崩溃了,此时会如何?会丢失数据吗?

肯定不会啊,因为虽然内存里的修改成name=月伴飞鱼的数据会丢失,但是redo日志里已经说了,对某某数据做了修改 name=月伴飞鱼。

所以此时mysql重启之后,他可以根据redo日志去恢复之前做过的修改

最后来看看,如果innodb_flush_log_at_trx_commit参数的值是2呢?

他的意思就是,提交事务的时候,把redo日志写入磁盘文件对应的os cache缓存里去,而不是直接进入磁盘文件,可 能1秒后才会把os cache里的数据写入到磁盘文件里去。

这种模式下,你提交事务之后,redo log可能仅仅停留在os cache内存缓存里,没实际进入磁盘文件,万一此时你要 是机器宕机了,那么os cache里的redo log就会丢失,同样会让你感觉提交事务了,结果数据丢了

三种redo日志刷盘策略到底选择哪一种?

innodb_flush_log_at_trx_commit=0 提交事务的时候,不会将内存中的redo log刷入磁盘

优点,纯内存操作速度快,缺点,redo日志没有落地磁盘,如果提交事务的一瞬间,MySQL宕机,那么如果是修改数据,内存数据没了,磁盘也没来的及更新,就丢失了本次修改操作。

innodb_flush_log_at_trx_commit=1,提交事务之前一定会将redo log 刷入磁盘

优点,事务提交之前,事务操作log一定刷入磁盘,事务成功,磁盘一定有redo日志,如果事务提交成功,内存修改,磁盘还没有更新,完全可以读取redo日志恢复数据。缺点,写磁盘确实会消耗很多性能,如果是高并发,大量写入,一定会影响写入性能,吞吐量和处理时间都会影响到。

innodb_flush_log_at_trx_commit=2,将redo日志刷入OS cache,间隔可能一秒写入磁盘。方案鉴于一和二方案之间。

优点,利用OS cache去缓存部分日志,可以提高吞吐量,间隔时间,异步刷入磁盘。缺点,提交事务之后,可能redo日志还在cache中。此时,日志存在丢失的风险。

三种方案,第一种方案适用于,允许不重要的数据,但是大批量插入的场景,可能丢失,比如一些大批量的任务执行日志上报的数据。

方案二适用于数据不可丢失的插入更新,比如订单,用户等核心数据。

方案三,适用于高并发插入,允许一定数据丢失,但是大部分可靠的场景,比如用户行为日志,APP异常上报等。

一般建议redo日志刷盘策略设置为1,保证事务提交之后,数据绝对不能丢失,MySQL中这个参数默认值为1

参考:

从零开始带你成为MySQL实战优化高手

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
存储 SQL 关系型数据库
MySQL存储引擎
本文介绍了数据库优化的多个方面,包括选择合适的存储引擎、字段定义原则、避免使用外键和触发器、大文件存储策略、表拆分及字段冗余处理等。强调了从业务层面进行优化的重要性,如通过活动设计减少外部接口调用,以及在高并发场景下的流量控制与预处理措施。文章还提供了具体的SQL优化技巧和表结构优化建议,旨在提高数据库性能和可维护性。
MySQL存储引擎
|
19天前
|
存储 缓存 关系型数据库
【赵渝强老师】MySQL的MyISAM存储引擎
在MySQL5.1版本之前,默认存储引擎为MyISAM。MyISAM管理非事务表,提供高速存储和检索,支持全文搜索。其特点包括不支持事务、表级锁定、读写互阻、仅缓存索引等。适用于读多、写少且对一致性要求不高的场景。示例代码展示了MyISAM存储引擎的基本操作。
|
19天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL的InnoDB存储引擎
InnoDB是MySQL的默认存储引擎,广泛应用于互联网公司。它支持事务、行级锁、外键和高效处理大量数据。InnoDB的主要特性包括解决不可重复读和幻读问题、高并发度、B+树索引等。其存储结构分为逻辑和物理两部分,内存结构类似Oracle的SGA和PGA,线程结构包括主线程、I/O线程和其他辅助线程。
【赵渝强老师】MySQL的InnoDB存储引擎
|
19天前
|
存储 关系型数据库 MySQL
【赵渝强老师】MySQL的Memory存储引擎
MySQL 的存储引擎层负责数据的存储和提取,支持多种存储引擎,如 InnoDB、MyISAM 和 Memory。InnoDB 是最常用的存储引擎,从 MySQL 5.5.5 版本起成为默认引擎。Memory 存储引擎的数据仅存在于内存中,重启后数据会丢失。示例中创建了使用 Memory 引擎的 test3 表,并展示了数据在重启后消失的过程。
|
3月前
|
存储 缓存 关系型数据库
MySQL高级篇——存储引擎和索引
MyISAM:不支持外键和事务,表锁不适合高并发,只缓存索引,内存要求低,查询快MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM不支持事务、行级锁、外键,有一个毫无疑问的缺陷就是崩溃后无法安全恢复。5.5之前默认的存储引擎优势是访问的速度快,对事务完整性没有要求或者以SELECT、INSERT为主的应用针对数据统计有额外的常数存储。故而 count(*) 的查询效率很高表名.frm 存储表结构;表名.MYD 存储数据 (MYData);
MySQL高级篇——存储引擎和索引
|
4月前
|
存储 关系型数据库 MySQL
MySQL 中的事务存储引擎深入解析
【8月更文挑战第31天】
57 0
|
6月前
|
存储 关系型数据库 MySQL
|
5月前
|
存储 关系型数据库 MySQL
MySQL InnoDB存储引擎的优点有哪些?
上述提到的特性和优势使得InnoDB引擎非常适合那些要求高可靠性、高性能和事务支持的场景。在使用MySQL进行数据管理时,InnoDB通常是优先考虑的存储引擎选项。
180 0
|
6月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第一篇(存储引擎与Linux系统上安装MySQL数据库)
MySQL数据库进阶第一篇(存储引擎与Linux系统上安装MySQL数据库)
|
6月前
|
存储 算法 关系型数据库
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
52 1