首页 > 数据库 >【MySQL架构】图解

【MySQL架构】图解

时间:2025-01-17 21:21:50浏览次数:1  
标签:架构 log Buffer redo 索引 MySQL 磁盘 图解 数据

你是一个程序员,你做了一个网站应用,站点里的用户数据,需要存到某个地方,方便随时读写。

很容易想到可以将数据存到文件里。

但如果数据量很大,想从大量文件数据中查找某部分数据,并更新,是一件很痛苦的事情。

那么问题就来了,有办法可以解决这个问题吗?

好办,没有什么是加一层中间层不能解决的,如果有,那就再加一层。

这次我们要加的中间层是 mysql。

【图】mysql是数据和应用的中间层

一、什么是 mysql

Mysql数据库,是一款存放和管理数据的软件, 它介于应用数据之间,通过一些设计,将大量数据,变成一张张像 excel 的数据表。为应用提供创建(Create), 读取(Read), 更新(Update), 删除(Delete)等核心操作。

【图】mysql是什么

我们来看下它是怎么实现的。

二、数据页

mysql 将数据组织成 excel 表的样子。

excel 文件在磁盘上是个xls 文件,mysql 的数据表也类似,在磁盘上则是个ibd 后缀的文件。

【图】ibd文件是什么

数据表越大,磁盘上的 ibd 文件也就越大。

直接读写一个大文件里的全部数据会很慢,所以 MySQL 将数据拆成一个个数据页,每页大小 16KB。这样我们读写部分表数据的时候,就只需要读取磁盘里的几个数据页就好。

【图】mysql将文件分成多个数据页

三、索引

但数据页那么多,查某条数据时,怎么知道要读哪些数据页?

好办,可以为每个数据页加入页号,再为每行数据加个序号,这个序号其实就是所谓的主键。

按主键大小排序,将每个数据页里最小的主键序号所在页的页号提出来,放入到一个新生成的数据页中,并且给数据页加入层级的概念。

这样我们就可以通过上层的数据页快速缩小查找范围,加速查找数据页的过程。

现在页跟页之间看起来就像是一棵倒过来的树,这棵可以加速查找数据页的树,就是我们常说的B+树索引。

【图】B+树索引

上面提到的是针对主键的索引,也就是主键索引

【图】主键索引

按同样的思路,也可以为其他数据表的列去建立索引,比如用户表的名称字段,这样我们就能快速查找到名字为 xx 的用户有哪些,这就是所谓的辅助索引

【图】辅助索引

四、Buffer Pool

但就算有了索引,数据也还是在磁盘上。每次都读磁盘太慢了。有办法提升下性能吗?

有!在磁盘数据应用之间,加一层进程内缓存,缓存里装的就是前面提到的 16KB 数据和索引页, 它就是所谓的 Buffer Pool

【图】buffer pool是什么

读数据的时候优先读 Buffer Pool,有数据就返回,没数据才去磁盘里读取,减少了读磁盘的次数,大大提升了性能。

但问题就来了,我们知道,文件读取,默认会先将文件数据加载到操作系统的文件缓存中,同样都是缓存,为什么还要整 Buffer Pool 这死出?

这是因为进程自己维护的 Buffer Pool ,可以定制更多缓存策略,还能实现加锁等各种数据表高级特性

也正是因为已经有了 Buffer Pool,所以也就没必要使用操作系统的文件缓存了,所以 Buffer Pool 通过"直接 I/O" 模式, 绕过操作系统的缓存机制,直接从磁盘读写数据。

【图】buffer pool直接IO

五、自适应 hash 索引

就算有了 buffer pool,要查到某个数据页,也依然要查找 B+树,查询复杂度 O(lgn)。能更快吗?

能!可以使用查询复杂度为 O(1)的 hash 表进行优化。

记录每个数据页的查询频率,对于热点数据页,我们以查询的key数据页地址value,构建 hash 表。

比如name为 'xiaobai' 的数据页,被频繁查询,那 key 就是 xiaobai,value 就是包含 xiaobai 记录的数据页的地址。

【图】哈希的key和value

这个 hash 表,就是所谓的自适应哈希索引,Adaptive Hash Index。

【图】自适应哈希

六、Change Buffer

有了自适应 hash 索引的加持,读性能提高了。那写性能也能优化吗?

能!

大部分数据表,除了主键索引外,我们还会加一些辅助索引。比如对用户名加个辅助索引

那对于这类数据表的写操作,更新完主键索引的数据页之后,还需要更新辅助索引页。这样读取辅助索引页的磁盘 IO 必然少不了。

【图】更新主键和辅助索引

怎么办呢?我们可以先将要写入的数据收集到一块内存里,等哪天磁盘里的索引页正好被读入 Buffer pool 的时候,再将写入数据应用到索引页中。

通过这个方式减少大量的磁盘 IO,提升性能。

而这个将写操作收集起来的地方,就是所谓的 Change Buffer,它其实是 Buffer pool 的一部分。

【图】Change Buffer的更新流程

七、Undo Log

在数据库中,有一个叫事务的概念。不了解没关系,说白了,就是可以让多行数据,要么同时更新成功,要么同时更新失败

也就是所谓的原子性

【图】事务是什么

为了实现这一点,我们就需要知道写数据时每行数据原来长啥样,方便对更新后的数据行,进行回滚,因此就有了 Undo Log

【图】undo log回滚

更新 buffer pool 数据页的时候,

会用旧数据生成 undo log 记录,存储在 Buffer Pool 中的特殊 undo log 内存页中。

并随着 buffer pool 的刷盘机制,不定时写入到磁盘的undo log中。

【图】undo log的写入流程

八、Redo Log

上面提到的都是 buffer pool 相关的内容,它们本质上都是内存。

如果内存数据只写了一半到磁盘中,数据库进程就崩了,那一个事务里的多行数据就没能做到"同时更新成功"。

怎么办呢?

好办,我们将事务中更新数据行的操作都写入到redo log buffer内存中,然后在事务提交的时候进行 redo log 刷磁盘,将数据固化到 redo log 文件中。

数据库进程崩溃重启后,就能通过 redo log file 找到历史操作记录,重做数据。保证了事务里的多行数据变更,要么都成功,要么都失败。

【图】redo log的写入流程

这时候问题就来了,我有这功夫更新 redo log file 文件,直接将 buffer pool 的数据写入到磁盘不香吗?

【图】为什么不直接写磁盘数据页

不太一样,redo log file 是顺序写入的,buffer pool 的内存数据是随机分散在磁盘各处的,顺序写磁盘性能是随机写的几十倍,所以很多存储系统在写数据时都会搞个日志来记录操作,方便服务重启后进行数据对账,确保数据的一致性和完整性,这类操作就是所谓的Write-Ahead Logging (WAL)

【图】顺序写比随机写快很多

但问题又来了,redo log buffer 也是内存,buffer pool 也是内存,如果 redo log buffer 里的数据还没来得及写入到 redo log,数据库进程就崩了,那 redo log buffer 里的数据不也丢了吗?

是的,所以 redo log 的作用并不是保证所有数据不丢失,而是确保已提交事务的变更不会丢失。但因为 redo log 刷盘频率很高,所以丢失数据的概率很低。

redo log 本质上是写入性能和数据完整性折中的产物,做架构就是这样,做到最后总是需要通过牺牲某些东西去换取另一样东西,果然,程序员才是真正的炼金术师。

九、Innodb 是什么

我们将上面提到的内容,分为内存磁盘两部分,一部分是内存里的自适应哈希,buffer pool,以及 redo log buffer。另一部分是磁盘里存放行数据和索引的.ibd 文件, 以及 undo log, redo log 等文件。它们共同构成了 innodb 存储引擎。并对外提供一系列函数接口。

比如操作数据行的 write_row(), update_row(),以及操作数据表的 create(), drop()等等接口。

我们平时写的 SQL 语句,最终都会转换成 InnoDB 提供的这些接口函数调用。

【图】innodb提供的函数接口

比如:

• INSERT 语句会调用 write_row() 接口来插入数据行。

• UPDATE 语句会调用 update_row() 接口来更新数据行。

• CREATE TABLE 语句会调用 create() 接口来创建新表。

• DROP TABLE 语句会调用 drop() 接口来删除表。

但问题就来了,我们平时读写 mysql 用的 sql 语句,是怎么转成存储引擎的函数接口的呢?

那就需要介绍 Server 层了。

十、Server 层是什么

Server 层,本质上是 sql 语句 和 innodb 存储引擎之间的中间层。

【图】server层

在 Server 层内提供一个连接管理模块,用于管理来自应用的网络连接。

并提供一个分析器,用于判断 SQL 语句有没有语法错误,比如 select,是不是少打了一个l。

再提供一个优化器,用于根据一定的规则选择该用什么索引,生成执行计划。

之后,提供一个执行器,根据执行计划去调用Innodb 存储引擎的接口函数。

【图】server层做了哪些事情

server 层存储引擎层共同构成了一个完整的数据库,它就是我们常说的 Mysql 数据库

【图】mysql是什么

并且,server 层和存储引擎层是通过接口函数进行解耦的,换句话说就是,只要实现了上面这些接口函数,就能作为存储引擎与 Server 层对接。

【图】引擎解耦

比如,mysql 早期用的是myisam存储引擎,后来才支持的 innodb

【图】常用存储引擎有哪些

十一、binlog 是什么

你听说过删库跑路吧,为了防止数据库表被删除带来的影响, server 层会将历史上所有变更操作记录到磁盘上的日志文件中,这个日志文件就是所谓的 binlog。一旦误删表,就可以利用 binlog 来恢复数据。

那么问题就来了,innodb 有一个 redo log 也做类似的事情,为什么还要多此一举?评论区告诉我答案。

这是因为 redo log 是环状写入的,后面写的内容最终会覆盖前面的内容,也就是不会记录所有历史写操作,而 binlog 却会记录所有历史变更。并且 binlog 位于 server 层,这样不管底层的存储引擎是什么,都能复用这部分能力。

【图】binlog写入流程

十二、Mysql 主从架构

由于 binlog 记录了一个 mysql 的所有变更操作,因此我们还可以利用 binlog 数据,"复制"一个新的 mysql 出来。

原来的 master 叫主数据库,复制出来的则是从数据库,数据库负责承接写流量,数据库负责读流量,这样就可以让 mysql 承接更高的读写流量。

它就是经典的 mysql 主从同步架构

十三、数据库查询更新流程

接下来我们用实际例子将上面提到的内容串起来。
首先不管是查询还是更新操作,客户端都会先跟 mysql 建立网络连接,并将 sql 发送到 server 层,经过分析器解析 sql 语法、优化器选择索引生成执行计划,最终给到执行器调用 InnoDB 的函数接口。

• 对于读操作。InnoDB存储引擎会先检查 Buffer Pool 中是否存在所需的 B+树数据页,如果存在则直接返回数据。

如果 Buffer Pool 中没有所需的数据页,则会从磁盘中读取相应的数据页加载到 Buffer Pool 中,再返回数据。

同时,如果查询的数据是热点数据,还会将数据页加入到自适应哈希索引豪华套餐中,加速后续的查询。

• 对于写操作,则会先将数据写入 Buffer Pool,并生成相应的 Undo Log 记录,以便在事务回滚时能够恢复数据的原始状态。

接下来,会将写操作记录到 Redo Log Buffer 中,这些 redo log 会周期性地写入到磁盘中的 Redo Log 文件中,就算数据库崩了,已提交的事务也不会丢失。

对于辅助索引的更新操作,InnoDB 会将这些更新暂时存储在 Change Buffer 中,等到相关的索引页被读取到 Buffer Pool 时再进行实际的更新操作,从而减少磁盘 I/O,提高写入性能。

同时,所有的变更都会记录到 server 层的 binlog 中,以便进行数据恢复。

【图】mysql架构总览图

现在大家通了吗?

总结

• mysql 分为 server 层和存储引擎层。存储引擎层可更换,既可以是 myisam,也可以是 innodb。当前用 innodb 更多。

• innodb 分为内存和磁盘两部分,一部分是内存里的自适应 hash,buffer bool,以及 redo log buffer。另一部分是磁盘里存放行数据和索引的.ibd 文件, 以及 undo log, redo log 等文件。

• mysql server 层会通过 binlog 记录数据库变更操作,binlog 可以用于数据恢复,也可以用于主从同步等场景。

原创 靓仔白 小白debug

标签:架构,log,Buffer,redo,索引,MySQL,磁盘,图解,数据
From: https://www.cnblogs.com/o-O-oO/p/18677646

相关文章

  • 彻底讲清楚 单体架构、集群架构、分布式架构及扩展架构
    目录什么是系统架构单体架构介绍示例图优点缺点集群架构介绍示意图优点缺点分布式架构示意图优点缺点生态扩展介绍示意图优点缺点扩展:分布式服务解析纵切拆服务全链路追踪能力循环依赖全链路日志(End-to-EndLogs)阅前提醒:前后端分离架构是前后端之......
  • 【RabbitMQ】图解
    你是一个程序员,假设你维护了两个服务A和B。A服务负责转发用户请求到B服务,B服务是个算法服务,GPU资源有限,当请求量大到B服务处理不过来的时候,希望能优先处理会员用户的请求。那么问题就来了,如果普通用户和会员用户同时发起请求,怎样才能做到会员优先呢?好办,没有什么是加......
  • 【MySQL】:事务
    朋友们、伙计们,我们又见面了,本期来给大家带来数据库事务的知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!C语言专栏:C语言:从入门到精通数据结构专栏:数据结构个 人 主 页 :stackY、C++专栏  :C++Linux专 栏 :Linux目录1.......
  • 【SQL教程】Day01-03: MySQL简介及安装指南
    MySQL是目前应用最广泛的开源关系数据库管理系统。它最初由瑞典的MySQLAB公司开发,后来该公司在2008年被SUN公司收购,紧接着在2009年SUN被Oracle公司收购,从而使得MySQL成为Oracle旗下的产品。MySQL的特点和发展历程使其成为全球许多企业和开发者的首选数据库。1.MySQL架构概览......
  • 免费送源码:Java+ssm+MySQL 基于SSM的游戏论坛设计与实现 计算机毕业设计原创定制
     摘 要本论文主要论述了如何使用SSM框架开发一个游戏论坛,将严格按照软件开发流程进行各个阶段的工作,采用B/S架构JAVA技术,面向对象编程思想进行项目开发。在引言中,作者将论述游戏论坛的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行各个阶段分析设计......
  • 免费送源码:Java+ssm+MySQL 基于ssm校园商城系统小程序 计算机毕业设计原创定制
    摘 要随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,校园商城系统小程序被用户普遍使用,为方便用户能够可以随时进行校园商城系统小程序的数据信息管理,特开发了基于ssm校园商......
  • 免费送源码:Java+ssm+MySQL Springboot大学生心理健康咨询小程序 计算机毕业设计原创定
    摘 要科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中,应用软件的工作规则和开发步骤,采用java技术建设大学......
  • 【书籍连载】《软件测试架构实践与精准测试》 川模型组织架构分析
    各位软件领域的精英们,今天小编邀请你继续深入学习《软件测试架构实践与精准测试》。《软件测试架构实践与精准测试》是作者李龙(安畅检测首席技术专家)基于软件测试“川模型”的著作。本书结合作者首次提出的软件测试新的模型“川模型”测试架构,并与精准测试理念相结合的方式,......
  • 基于 KubeSphere v4 的 Kubernetes 生产环境部署架构设计及成本分析
    本文作者:运维有术。今天分享的主题是:如何规划设计一个高可用、可扩展的中小规模生产级K8s集群?通过本文的指导,您将掌握以下设计生产级K8s集群的必备技能:集群规划能力合理规划节点规模和资源配置设计高可用的控制平面、计算平面、存储平面架构规划网络拓扑和安全策略制......
  • DeepSeek-V3 的 MoE 架构解析:细粒度专家与高效模型扩展
    DeepSeek-V3采用的DeepSeekMoE架构,通过细粒度专家、共享专家和Top-K路由策略,实现了模型容量的高效扩展。每个MoE层包含1个共享专家和256个路由专家,每个Token选择8个路由专家,最多路由至4个节点。这种稀疏激活的机制,使得DeepSeek-V3能够在不显著增加计算成本的......