MySQL原理简介—2.InnoDB架构原理和执行流程

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 本文介绍了MySQL中更新语句的执行流程及其背后的机制,主要包括:1. **更新语句的执行流程**:从SQL解析到执行器调用InnoDB存储引擎接口。2. **Buffer Pool缓冲池**:缓存磁盘数据,减少磁盘I/O。3. **Undo日志**:记录更新前的数据,支持事务回滚。4. **Redo日志**:确保事务持久性,防止宕机导致的数据丢失。5. **Binlog日志**:记录逻辑操作,用于数据恢复和主从复制。6. **事务提交机制**:包括redo日志和binlog日志的刷盘策略,确保数据一致性。7. **后台IO线程**:将内存中的脏数据异步刷入磁盘。

大纲

1.更新语句在MySQL中是如何执行的

2.重要的内存结构—Buffer Pool缓冲池

3.undo日志文件如何让更新的数据可以回滚

4.更新Buffer Pool缓冲池中的缓存数据

5.Redo Log Buffer如何避免宕机时数据丢失

6.如果还没提交事务时MySQL宕机了怎么办

7.提交事务时将redo日志写入磁盘中

8.redo日志刷盘策略的选择和建议

9.MySQL的redo log和binlog对比

10.提交事务时同时也会写入binlog

11.binlog日志的刷盘策略分析

12.基于binlog的redo log完成事务的提交

13.在redo日志中写入commit标记的意义

14.后台IO线程随机将内存更新后的脏数据刷盘

15.InnoDB存储引擎的架构原理总结

 

这里主要介绍MySQL的数据缓存机制

 

1.更新语句在MySQL中是如何执行的

假设有一条如下这样的SQL语句,那么这条语句是如何执行的呢?

update users set name = 'xxx' where id = 1;

首先Java系统会通过一个数据库连接将该SQL语句发送到MySQL上,然后经过SQL接口、查询解析器、查询优化器、执行器环节,在解析出了SQL语句、生成了执行计划后,再由执行器调用InnoDB存储引擎的接口去执行生成的执行计划。

下面介绍InnoDB存储引擎里的架构设计,以及如何基于InnoDB存储引擎完成一条更新语句的执行。

 

2.重要的内存结构—Buffer Pool缓冲池

InnoDB有一个非常重要、放在内存里的组件,就是缓冲池(Buffer Pool)。缓冲池会缓存很多磁盘文件数据,以便在查询时不用去查磁盘。如下图示:

所以当InnoDB存储引擎要执行更新语句时:比如对"id=1"这一行数据,会先判断"id=1"这一行数据是否在缓冲池里。如果不在,则直接从磁盘里加载到缓冲池里,且对这行记录加独占锁。

 

3.undo日志文件如何让更新的数据可以回滚

假设"id=1"这行数据的name原来是"zhangsan",现在要更新为"xxx"。那么InnoDB得先把原值"zhangsan"和"id=1"写入到undo日志文件中。

 

Java系统在执行一条SQL更新语句时,要是它在一个事务里,那么事务提交前是可以对数据进行回滚的。所以考虑到可能要回滚数据,InnoDB会把更新前的值写入undo日志文件。如下图示:

 

4.更新Buffer Pool缓冲池中的缓存数据

当InnoDB把要更新的那行记录从磁盘文件加载到了缓冲池,同时对它加完锁,而且还把更新前的旧值写入undo日志文件后,InnoDB就可以正式开始更新这行记录了。

 

更新的时候,会先更新缓冲池中的记录,此时这个数据就是脏数据了。所谓的更新内存缓冲池里的数据,意思就是把内存里的"id=1"这行数据的name字段修改为"xxx"。

 

为什么说此时这行数据是脏数据呢?因为这时磁盘上"id=1"这行数据的name字段还是"zhangsan",但内存里这行数据已经被修改了,所以它是脏数据。

 

5.Redo Log Buffer如何避免宕机时数据丢失

现在已经把内存里的数据进行了修改,但是磁盘上的数据还没修改。此时万一MySQL所在机器宕机,必然会导致内存里已修改的数据丢失。这该如何处理?

 

为此必须把对内存所做的修改写入一个Redo Log Buffer里,Redo Log Buffer也是内存里的一个缓冲区,是用来存放redo日志的。

 

所谓redo日志,就是记录InnoDB要对数据做什么修改。比如对"id=1"这行记录修改name字段的值为"xxx",就是一条redo日志。

 

6.如果还没提交事务时MySQL宕机了怎么办

在数据库中,哪怕执行一条SQL语句,其实也可以是一个独立的事务。只有当事务提交后,SQL语句才算执行结束。

 

所以如果还没提交事务MySQL宕机了,那么必然导致内存里Buffer Pool中修改过的数据都丢失,同时写入Redo Log Buffer中的日志也会丢失。

此时数据丢失其实是不要紧的。因为一条更新语句只要没提交事务,那么就代表还没执行成功。此时MySQL宕机虽然导致内存里的数据丢失,但还没影响磁盘上的数据。

 

7.提交事务时将redo日志写入磁盘中

如果InnoDB想要提交一个事务,就会根据一定的策略把redo日志从Redo Log Buffer中刷入到磁盘文件里,这个策略是通过如下这个参数来配置的:innodb_flush_log_at_trx_commit。

 

(1)当innodb_flush_log_at_trx_commit = 0时

那么进行事务提交时,不会把Redo Log Buffer的数据刷入到磁盘文件里。这时即便提交了事务,但如果MySQL宕机了,内存里的数据也会全部丢失而且redo日志里没有数据。

 

(2)当innodb_flush_log_at_trx_commit = 1时

那么进行事务提交时,会把内存中的redo log刷入到磁盘文件里。只要事务提交成功,那么redo log就必然在磁盘里。哪怕此时Buffer Pool中更新过的数据还没刷新到磁盘,系统崩溃重启后,也可以根据磁盘中的redo log恢复。

 

(3)当innodb_flush_log_at_trx_commit = 2时

那么进行事务提交时,会把内存中的redo log写入到OS Cache缓存里。OS Cache缓存里的数据可能在1秒后才会被写入到磁盘文件中。

 

在这种模式下,当InnoDB存储引擎提交事务后,redo log可能还停留在OS Cache缓存里,还没实际进入到磁盘文件。而此时MySQL所在机器宕机了,那么OS Cache里的redo log也会丢失。从而出现即便提交了事务,但是数据还是丢失了的情况。

 

8.redo日志刷盘策略的选择和建议

通常建议设置innodb_flush_log_at_trx_commit的值为1。也就是提交事务时,redo日志必须同时刷入磁盘文件里。这样可以严格保证提交事务后数据绝对不会丢失。

 

如果innodb_flush_log_at_trx_commit = 0,那么提交事务后如果MySQL宕机而此时redo日志还没有刷盘,则会导致内存里的redo日志丢失,内存更新好的数据也丢失。

 

如果innodb_flush_log_at_trx_commit = 2,那么提交事务后虽然redo日志进入了OS Cache,但OS Cache的数据此时还没进入磁盘文件而MySQL机器宕机了,则也会导致OS Cache的redo日志丢失。

 

所以一般设置redo日志刷盘策略为1,保证事务提交后数据不会丢失。

 

9.MySQL的redo log和binlog对比

MySQL的redo log,是一种偏向物理性的重做日志。因为其记录的是:对哪个数据页中的哪条记录做了什么修改。而且redo log是属于InnoDB存储引擎特有的日志文件。

 

MySQL的binlog,是一种偏向于逻辑性的日志,也叫归档日志。类似"对users表中id=1的一行记录做了更新操作,更新后的值是什么"。binlog不是InnoDB存储引擎特有的日志文件,binlog是属于MySQL数据库层面的日志文件。

 

10.提交事务时同时也会写入binlog

提交事务时,除了会把redo日志写入到磁盘文件中,还会把这次SQL更新对应的binlog日志写入到磁盘文件中。

 

下图加入了执行器这个组件,它会负责和InnoDB存储引擎进行交互:

步骤1:从磁盘加载数据到Buffer Pool缓存

步骤2:写入undo日志

步骤3:更新Buffer Pool里的数据

步骤4:写入redo日志到Redo Log Buffer

步骤5:redo日志刷入磁盘

步骤6:写入binlog日志

 

实际上,执行器是非常核心的一个组件。执行器会与存储引擎完成SQL语句在磁盘与内存层面的全部数据更新操作。

 

下图把一次更新语句的执行,拆分为两个阶段。其中步骤1、2、3、4是执行更新语句的阶段,而步骤5和6是属于提交事务的阶段。

 

11.binlog日志的刷盘策略分析

binlog日志也有不同的刷盘策略,通过sync_binlog参数可以控制binlog的刷盘策略,默认值是0。

 

(1)当sync_binlog设置为0时

表示执行器没有直接将binlog写入磁盘文件,而是先将binlog写入OS Cache缓存,与redo log的innodb_flush_log_at_trx_commit的值为2一样。

 

如果OS Cache里的数据还没写入磁盘文件时,MySQL所在机器宕机,那么binlog日志也会丢失。

 

(2)当sync_binlog设置为1时

表示在提交事务时,执行器会把binlog直接写入到磁盘文件中。这样在提交事务后即便宕机,binlog也不会丢失。

 

12.基于binlog的redo log完成事务的提交

当MySQL把binlog写入磁盘后,接着就会完成最终的事务提交。此时会把本次更新对应的binlog文件名称和位置,都写入到redo日志里,同时在redo日志文件里写入一个commit标记。在完成这个事情后,才算是最终完成事务的提交。

 

13.在redo日志中写入commit标记的意义

写入commit标记是用来保持redo日志与binlog日志一致。也就是说,在提交事务的时候,上图的步骤5、6、7必须都执行完毕,才算是提交了事务。

 

(1)如果刚完成步骤5时,redo日志刚刷入到磁盘文件,MySQL宕机了

这时因为在redo日志没有最终的事务commit标记,所以此次事务不成功。因为不允许出现这样的情况:redo日志文件里有更新日志,但是binlog日志文件里没有对应的更新日志。否则就会导致数据不一致。

 

(2)如果在完成步骤6时,binlog日志已写入磁盘,MySQL宕机了

这时因为在redo日志没有最终的事务commit标记,所以此次事务也失败。所以必须要在redo日志写入最终的事务commit标记,才算事务提交成功。这样redo日志有本次更新的日志,binlog日志也有本次更新的日志,从而实现redo日志和binlog日志完全一致。

 

14.后台IO线程随机将内存更新后的脏数据刷盘

当完成事务提交后,MySQL已把内存中的Buffer Pool缓存数据更新了,同时磁盘里也有redo日志和binlog日志,但磁盘上的数据文件还是旧值。

 

这时MySQL会有一个后台IO线程,在事务提交后的某个时间,随机把内存Buffer Pool中修改后的脏数据刷回到磁盘上的数据文件里。

 

当IO线程把Buffer Pool里修改后的脏数据刷回磁盘后,磁盘上的数据才会跟内存里的数据一样,都是修改后的值。

 

当IO线程把脏数据刷回磁盘之前,即便MySQL宕机也没关系。因为重启后会根据redo日志恢复提交事务时所做的修改到内存里。之后IO线程还是会把修改后的数据刷到磁盘的数据文件里。

 

15.InnoDB存储引擎的架构原理总结

InnoDB存储引擎会使用Buffer Pool、Redo Log Buffer来缓存数据。InnoDB存储引擎有属于自己的undo日志文件、redo日志文件,MySQL也有属于自己的binlog日志文件。

 

执行更新时:会修改Buffer Pool里的数据、写undo日志、写Redo Log Buffer。

 

提交事务时:会把binlog刷入磁盘、在redo日志中写入事务标记,把redo日志刷入磁盘。最后InnoDB后台的IO线程会随机把Buffer Pool的脏数据刷入到磁盘文件。

 

(1)MySQL宕机重启如何确定是否需要从redo日志恢复数据

MySQL宕机重启,如何确定脏数据在宕机前是否已全部刷写回磁盘文件。

 

MySQL宕机重启,InnoDB会首先去查看数据页中LSN的数值。LSN就是InnoDB使用的一个版本标记的计数。如果数据页中的LSN异于redo日志的commit标记,那么就去查看redo日志的LSN大小。如果数据页的LSN值大,则说明数据页领先redo日志,不需要恢复,反之则需要从redo日志中恢复。

 

(2)从redo日志恢复数据时是全量恢复还是指定位置后恢复

redo日志是划归于一个redo日志组的。默认一个redo日志组有两个redo日志文件。写redo日志时是循环写入,写满一个redo日志文件再写另外一个。

 

在写满切换redo日志文件时,会触发数据库的检查点checkpoint。checkpoint所做的事就是把脏页刷新回磁盘。

 

当DB重启恢复时只需要恢复checkpoint之后的数据即可。所以redo日志文件大小不宜过大,不然导致恢复时需要更长的时间。redo日志文件大小也不宜过小,不然导致频繁切换触发检测点降低性能。

 

(3)既然有redo日志来保证崩溃恢复,为什么还要有binlog日志

binlog日志其实就是归档日志,主要用来做数据恢复的。MySQL最开始设计时只有MyISAM引擎只有binlog,不支持InnoDB。此外数据库备份以及hadoop系统数据分析都是binlog来实现的,所以还需要binlog。

 

(4)redo日志和binlog日志的数据结构是怎样的

redo日志是循环写,会把redo日志分为0,1,2,3四个区间,有两个指针。writepos指针是一边写一边向后移动,checkpoint指针是一边擦除一边向后移动。所以redo日志是不能保存很多记录的,必须持久化到磁盘中。binlog日志是追加写,不会覆盖之前的日志。

 

(5)binlog日志和redo日志是怎么保持一致性的

binlog日志和redo日志是通过两阶段提交来保持一致性的。否则如果数据库系统发生crash,则通过redo日志恢复的数据库和通过binlog日志恢复出来的临时库不一致。

 

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
19天前
|
自然语言处理 搜索推荐 关系型数据库
MySQL实现文档全文搜索,分词匹配多段落重排展示,知识库搜索原理分享
本文介绍了在文档管理系统中实现高效全文搜索的方案。为解决原有ES搜索引擎私有化部署复杂、运维成本高的问题,我们转而使用MySQL实现搜索功能。通过对用户输入预处理、数据库模糊匹配、结果分段与关键字标红等步骤,实现了精准且高效的搜索效果。目前方案适用于中小企业,未来将根据需求优化并可能重新引入专业搜索引擎以提升性能。
|
1月前
|
关系型数据库 MySQL 数据库
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
随着数据量增长和业务扩展,单个数据库难以满足需求,需调整为集群模式以实现负载均衡和读写分离。MySQL主从复制是常见的高可用架构,通过binlog日志同步数据,确保主从数据一致性。本文详细介绍MySQL主从复制原理及配置步骤,包括一主二从集群的搭建过程,帮助读者实现稳定可靠的数据库高可用架构。
94 9
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
|
1月前
|
存储 关系型数据库 MySQL
MySQL底层概述—6.索引原理
本文详细回顾了:索引原理、二叉查找树、平衡二叉树(AVL树)、红黑树、B-Tree、B+Tree、Hash索引、聚簇索引与非聚簇索引。
MySQL底层概述—6.索引原理
|
1月前
|
SQL 监控 关系型数据库
MySQL原理简介—12.MySQL主从同步
本文介绍了四种为MySQL搭建主从复制架构的方法:异步复制、半同步复制、GTID复制和并行复制。异步复制通过配置主库和从库实现简单的主从架构,但存在数据丢失风险;半同步复制确保日志复制到从库后再提交事务,提高了数据安全性;GTID复制简化了配置过程,增强了复制的可靠性和管理性;并行复制通过多线程技术降低主从同步延迟,保证数据一致性。此外,还讨论了如何使用工具监控主从延迟及应对策略,如强制读主库以确保即时读取最新数据。
MySQL原理简介—12.MySQL主从同步
|
21天前
|
SQL 存储 缓存
MySQL的架构与SQL语句执行过程
MySQL架构分为Server层和存储引擎层,具有高度灵活性和可扩展性。Server层包括连接器、查询缓存(MySQL 8.0已移除)、分析器、优化器和执行器,负责处理SQL语句;存储引擎层负责数据的存储和读取,常见引擎有InnoDB、MyISAM和Memory。SQL执行过程涉及连接、解析、优化、执行和结果返回等步骤,本文详细讲解了一条SQL语句的完整执行过程。
41 3
|
1月前
|
SQL 关系型数据库 MySQL
数据库数据恢复——MySQL简介和数据恢复案例
MySQL数据库数据恢复环境&故障: 本地服务器,安装的windows server操作系统。 操作系统上部署MySQL单实例,引擎类型为innodb,表空间类型为独立表空间。该MySQL数据库没有备份,未开启binlog。 人为误操作,在用Delete命令删除数据时未添加where子句进行筛选导致全表数据被删除,删除后未对该表进行任何操作。
|
3月前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
4月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
97 3
|
4月前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
|
3月前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
369 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型

相关产品

  • 云数据库 RDS MySQL 版