1、全面理解MySQL的架构

MySQL 的基本架构示意图

各个模块的理解:

客户端

Navicat、JDBC连接工具都是客户端,用于连接和发送SQL请求

服务端

为 Server 层和存储引擎层两部分,Server层涵盖 MySQL 的大多数核心服务功能:

  • 负责处理 SQL 语句、解析、优化、缓存等。
  • 负责权限管理、用户认证等。
  • 提供了各种 SQL 处理函数、触发器、存储过程、视图等。
  • 提供了内置函数(如日期、时间、数学和加密函数等)
  • 提供了复制、备份、恢复等高级功能。
  • 提供 binlog(归档日志)功能。binlog 记录了所有修改数据库数据的 SQL 语句(如INSERT、UPDATE、DELETE 等)的信息,但不包括 SELECT 和 SHOW 这类查询语句。binlog 主要用于复制和恢复操作。

存储引擎层的存储引擎则是以插件的形式存在的,MySQL 支持多种存储引擎在最常用的存储引擎是 InnoDB,InnoDB支持事务、行级锁定和外键约束。这是MySQL5.5.5版本及之后的默认引擎。其他的引擎还有MyISAM、Memory等。存储引擎层负责如下功能:

  • 负责数据的存储和检索
  • 提供日志系统,有 redo log(重做日志) 和 undo log(撤销日志)。redo log 用于保证事务的持久性,在数据库崩溃后可以用来恢复数据;undo log 用于支持事务的原子性和多版本并发控制(MVCC)。

一条SQL查询语句是怎么被执行的

1、通过连接器建立连接,数据库的连接是长连接,连接时长由参数wait_timeout控制,由于建立连接的过程比较复杂,因此,在实际应用中通常要尽量减少连接动作,并使用连接池。

2、查询缓存,这里不做展开,只需大概了解MySQL为什么在8.0后移除了缓存功能

3、在分析器中进行词法分析和语法分析,词法分析负责中提取关键字,比如:查询的表,字段名,查询条件等,语法分析负责判断SQL 语句是否满足 MySQL 语法。

4、SQL语句进入优化器,优化器的作用是在基于同一个查询语句的多个查询方案中找出效率最高的。常见的优化策略是小表驱动大表。

5、执行器阶段,先判断是否有操作权限,然后才是执行操作

思考:如果表T中没有字段 k,而你执行了这个语句 select*from Twhere k=1,那肯定是会报"不存在这个列"的错误:"Unknown column'k' in'where clause""。请问是在哪个阶段报出的错误? 分析器

一条SQL更新语句是怎么执行的

连接器->缓存->分析器->优化器->执行器,总体流程与查询的相似,但有不一样的地方,更新流程还涉及两个重要的日志模块:redo log(重做日志)和 bin log(归档日志)

如何理解redo log和bin log

以《孔乙己》 的故事来比喻:酒店掌柜有一个粉板(白漆的木板),专门用来记录客人的赊账记录。如果赊账的人不多,那么他可以把顾客名和账目写在板上。但如果赊账的人多了,粉板总会有记不下的时候,这个时候掌柜一定还有一个专门记录赊账的账本。如果有人要赊账或者还账的话,掌柜一般有两种做法:一种做法是直接把账本翻出来,把这次赊的账加上去或者扣除掉;·另一种做法是先在粉板上记下这次的账,等打烊以后再把账本翻出来核算。在生意红火柜台很忙时,掌柜一定会选择后者,因为前者操作实在是太麻烦了。

这里,粉板就是MySQL 的 WAL 技术(Write-Ahead Logging,预写式日志),账本就是磁盘。

具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log(粉板)里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘(账本)里面,而这个更新往往是在系统比较空闲的时候做,好比掌柜的在打烊以后再整理账本一样。

这里有一个问题:InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是1GB,那么这块"粉板"总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写,如图所示。

write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。
checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

write pos 和 checkpoint 之间的是"粉板"上还空着的部分,可以用来记录新的操作。如果 write pos 追上checkpoint,表示"粉板"满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint推进一下。

有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。

为什么有binlog和redo log两种日志

最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是MyISAM 没有crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的。只依靠 binlog 是没有 crash-safe 能力的,所以InnoDB 使用另外一套日志系统--也就是 redo1og 来实现 crash-safe 能力。

两种日志的不同点:

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
  2. redo log 是物理日志,记录的是"在某个数据页上做了什么修改";binog 是逻辑日志,记录的是这个语句的原始逻辑,比如"给 ID=2 这一行的c字段加1"。redo log 是从数据页的角度来看的,它关心的是数据在磁盘上的物理布局和如何高效地修改这些数据。binlog 是从 SQL 语句的角度来看的,它关心的是执行了哪些操作以及这些操作的内容。
  3. redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。"追加写"是指binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

两种日志的结合,使得 MySQL 既能保证事务的 ACID 属性,又能支持高效的数据复制和恢复。当执行一个事务时,相关的更改会先写入 redo log,然后执行 SQL 语句并将更改写入 binlog。这样,即使在数据库系统崩溃的情况下,也可以通过这两个日志来恢复数据。

思考:某个时间点做的误删操作应当如何恢复?

  • 找到最近的一次全量备份(这需要对数据做定期备份,如一天一备)
  • 从备份的时间点开始,将备份的 binlog 依次取出来,重放到中午误删表之前的那个时刻。

UPDATE的执行流程图

绿色的是在存储引擎中执行,棕色的是在Server层执行

MySQL的两阶段提交

思考:

1、如果不使用两阶段提交,会出现什么问题?

2、举例说明两阶段提交是如何保证恢复数据并保证一致性的?

相关推荐
G31135422733 小时前
Linux 内核设计中的核心思想与架构原则
linux·架构·php
Xの哲學5 小时前
Linux VxLAN深度解析: 从数据平面到内核实现的全面剖析
linux·服务器·算法·架构·边缘计算
2301_768350235 小时前
MySQL架构长啥样?
架构
古城小栈6 小时前
微服务网格:Istio 流量管理实战
微服务·架构·istio
CloudWeGo8 小时前
Volo 新能力:面向易用性与性能的 HTTP & RPC 框架迭代
架构
^_scv_^8 小时前
QEMU-RISCV平台opensbi代码分析(2)
linux·架构·risc-v
狗哥哥8 小时前
企业级 HTTP 客户端架构演进与设计
前端·架构
前端阿森纳9 小时前
公司是否因为AI正在从“以人为本”走向“以核心数据集为本”?
架构·aigc
小宝哥Code9 小时前
区块链(Blockchain)—— 概念、架构与应用
架构·区块链