MySQL是一个广泛使用的开源关系型数据库管理系统(RDBMS),它使用SQL(结构化查询语言)作为其主要的数据管理和操作语言。MySQL的设计采用客户端-服务器架构,其中客户端应用程序通过网络连接到MySQL服务器来执行各种数据库操作。
- 客户端:可以是任何支持MySQL协议的应用程序或工具,如MySQL命令行客户端、PHP脚本等。
- 服务器:运行MySQL服务的机器,负责处理来自客户端的所有请求。
MySQL的架构由多个层次和组件构成,主要包括连接层、核心服务层、存储引擎层和数据存储层。
连接层
MySQL的连接层(Connection Pool)主要负责建立客户端与服务器之间的TCP连接,并进行身份验证和权限获取。以下是连接层的主要组成和功能:
- TCP连接建立
- 三次握手:当客户端尝试连接MySQL服务器时,需通过TCP协议的三次握手过程来建立连接。
- socket监听:MySQL服务器在启动后创建一个socket server,绑定到3306端口,并持续监听新的连接请求。
- 身份验证和权限获取
- 用户名和密码验证:一旦TCP连接建立成功,服务器会对传输过来的账号密码进行身份认证,确保只有合法用户可以访问数据库。
- 权限分配:验证成功后,用户会被分配相应的权限,这些权限定义了用户能够执行的操作范围。
- 线程池管理
- 线程分配:每个成功建立的连接会从线程池中获取一个线程,省去了频繁创建和销毁线程的开销。
- 资源复用:通过维护线程池,MySQL能高效地管理客户端连接对应的后台工作线程,提高并发处理能力。
- 网络通信模型
- Poll/Select模型:MySQL采用IO多路复用技术,使用Poll或Select模型来管理网络连接,特别是在连接数较少时,性能优异。
- Max-connections设置:为防止过多的连接造成资源耗尽,MySQL通过max-connections参数限制最大连接数。
服务层
MySQL的服务层(MySQL Server)是其核心部分,负责处理SQL语句的解析、优化、缓存以及执行并返回结果。
SQL接口
SQL接口是服务层与客户端通信的前端部分。它接收来自客户端的SQL查询,这些查询可以是DDL(数据定义语言)、DML(数据操纵语言)、DCL(数据控制语言)或查询(SELECT)语句。
- 解析SQL语句:SQL接口解析客户端发送的SQL语句,并检查其语法是否正确。
- 处理客户端请求:根据SQL语句的类型,SQL接口确定如何处理请求,例如创建表、插入数据、更新数据或查询数据。
解析器
解析器是服务层中负责将SQL语句转换成解析树(Parse Tree)的组件。解析树的每个节点代表SQL语句的一个元素。
- 词法分析:将SQL语句分解成关键字、标识符、常量、操作符等元素。
- 语法分析:根据MySQL的语法规则,检查SQL语句的结构是否正确,并构建抽象语法树。
在解析过程中,还会验证客户端是否具有执行该语句的权限。
优化器
查询优化器是服务层中负责优化查询执行计划的组件。它分析解析器生成的解析树,并决定最有效的查询执行路径。
- 选择索引:确定使用哪些索引可以加快查询速度。
- 查询重写:优化器可能会重写查询,使其更加高效。
- 代价估算:根据存储引擎提供的统计信息,估计不同执行计划的成本(如I/O次数、CPU时间等),选择成本最低的计划。
缓存和缓冲区
服务层使用多种缓存和缓冲机制来提高性能。
在MySQL 8.0之前的版本中,服务层包含查询缓存组件,用于缓存SELECT语句的结果。
- 查询缓存(在MySQL 8.0之前):存储SELECT查询的结果,如果相同的查询再次执行,可以直接从缓存中返回结果,而不需要重新执行查询。MySQL 8.0之后,查询缓存被移除。
- 表缓存:缓存表的定义,减少打开和关闭表的开销。
- 权限缓存:存储用户的权限信息,加快权限检查的速度。
- 数据缓冲:InnoDB存储引擎使用缓冲池(Buffer Pool)来缓存数据和索引,减少磁盘I/O。
执行器
执行器在MySQL中负责执行经过优化器优化后的SQL语句。
执行器通过与存储引擎交互,实现数据的查询、更新、删除等操作,并将最终结果返回给用户。
- 调用存储引擎接口:执行器根据优化器生成的执行计划,调用存储引擎接口进行数据操作。
- 返回结果:完成查询或更新操作后,将结果返回给客户端。
存储引擎层
存储引擎层(Pluggable Storage Engines)是MySQL数据库架构中的关键部分,它负责处理数据的存储、检索、更新和删除等操作。MySQL支持插件式的存储引擎,这使得每种引擎可以针对不同的应用场景进行优化。
常用的存储引擎有InnoDB引擎和MyISAM引擎。
InnoDB
InnoDB是MySQL默认的存储引擎,专为事务处理设计,支持崩溃恢复、行级锁定等多种功能。
逻辑存储结构
- 表空间(ibd文件):每个MySQL实例可以有多个表空间,用于存储记录和索引等数据。
- 段:分为数据段、索引段和回滚段。数据段是B+树的叶子节点,索引段是B+树的非叶子节点。
- 区:是表空间的单元结构,每个区的大小为1MB,每个区包含64个连续的页。
- 页:是InnoDB存储引擎磁盘管理的最小单位,每页的默认大小为16KB。
- 行:数据按行存放,每次记录改动时,都会更新Trx_id和Roll_point隐藏列。
内存架构
- 缓冲池:主内存中的一个区域,用于缓存磁盘上经常操作的数据,以减少磁盘IO。缓冲池以页为单位,采用链表数据结构管理页,分为free page、clean page和dirty page三种类型。
- 更改缓冲区:针对非唯一二级索引页,减少磁盘IO。
- 自适应哈希索引:用于优化对Buffer Pool数据的查询,自动建立哈希索引。
- 日志缓冲区:保存要写入磁盘的log日志数据(redo log、undo log),默认大小为16MB。
磁盘结构
- 系统表空间:包含更改缓冲区的存储区域,可能包含表和索引数据。
- 独立表空间:每个表的文件表空间包含单个InnoDB表的数据和索引。
- 通用表空间:通过CREATE TABLESPACE语法创建,可用于多个表。
- 撤销表空间:用于储存undo log日志,初始化时会创建两个默认的undo表空间。
- 临时表空间:用于存储用户创建的临时表等数据。
- 双写缓冲区:在刷新数据页到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。
- 重做日志:用于实现事务持久性,由重做日志缓冲和重做日志文件组成。
后台线程
- Master Thread:核心后台线程,负责调度其他线程,并保持数据一致性。
- IO Thread:处理IO请求,提升数据库性能。包括读线程、写线程、插入缓冲线程和日志线程。
- Purge Thread:回收已经提交了的undo log。
- Page Cleaner Thread:协助Master Thread将脏页刷新到磁盘,减轻其工作负担。
文件组成
InnoDB是MySQL数据库中一个非常重要的存储引擎,它由多个文件组成,主要包括以下几类:
- 系统表空间文件(System Tablespace):
ibdata1
:这是默认的系统表空间文件,包含了InnoDB数据字典、双写缓冲区(doublewrite buffer)、更改缓冲区(change buffer)以及undo日志等信息。如果启用了多个表空间,可能会有ibdata2
、ibdata3
等文件。
- 独立表空间文件(File-Per-Table Tablespaces):
*.ibd
:每个InnoDB表可以有一个独立的表空间文件,通常以表名结尾的.ibd
文件形式存在。这些文件包含了表的数据和索引。
- 重做日志文件(Redo Log Files):
ib_logfile0
和ib_logfile1
:这些是InnoDB的重做日志文件,用于崩溃恢复。通常会有两个文件,它们以循环方式写入。
- 撤销日志文件(Undo Log Files):
- 如果 undo 表空间是独立的(不存储在系统表空间中),则可能会有
undo001
、undo002
等文件。
- 如果 undo 表空间是独立的(不存储在系统表空间中),则可能会有
- 事务日志文件(Transaction Log Files):
- 在一些配置下,InnoDB可以配置为将事务日志(redo log)写入到系统日志文件系统,而不是传统的
ib_logfile
。
- 在一些配置下,InnoDB可以配置为将事务日志(redo log)写入到系统日志文件系统,而不是传统的
- 表定义文件(Table Definition Files):
*.frm
:这是表结构定义文件,它记录了表的结构信息,但自MySQL 5.6.17之后,表结构信息被存储在系统表空间或独立表空间文件中,.frm
文件的重要性降低了。
- 通用日志文件(General Log File)和慢查询日志文件(Slow Query Log File)(如果启用):
- 这些日志文件虽然不是InnoDB引擎的一部分,但它们对于追踪数据库操作和性能调优非常有用。
- 其他可能的文件:
ib_buffer_pool
:从MySQL 5.7开始,InnoDB支持将缓冲池(buffer pool)的内容保存到一个文件中,以便在服务器重启后快速恢复。
索引结构
B+树索引
InnoDB使用B+树作为索引结构。B+树是一种自平衡的树,它维持数据的有序性,并允许在对数时间内进行搜索、顺序访问、插入和删除操作。
- 根节点和内部节点:这些节点包含多个键值和指向子节点的指针。它们不存储数据,只用于导航。
- 叶节点:叶节点包含所有的键值和对应的数据行或数据行的主键值。叶节点之间通过双向链表连接,便于全索引扫描。
聚簇索引
InnoDB中的聚簇索引(Clustered Index)是指数据行的物理顺序与索引顺序相同。每个表通常只有一个聚簇索引。
- 主键索引:如果表有主键,则InnoDB会自动使用主键创建聚簇索引。
- 数据行存储:数据行直接存储在聚簇索引的叶节点中。
- 非主键索引:非主键索引(二级索引)包含主键值作为指向数据行的指针。
二级索引
除了聚簇索引外,表可以拥有多个二级索引(Secondary Index)。
- 包含索引列:二级索引的叶节点包含索引列的值和对应的主键值。
- 额外存储空间:每个二级索引都需要额外的存储空间。
- 多列索引:可以基于表中的多个列创建复合索引。
最左前缀原则
最左前缀原则(Leftmost Prefix Principle)是指在复合索引中,查询条件必须使用索引的第一个列,并且如果索引由多个列组成,那么查询条件中的列必须按照索引定义的顺序出现。
复合索引的结构
复合索引在B+树中的存储方式是将索引列的值组合成一个键值。例如,假设有一个复合索引(a, b, c)
,则索引中的键值看起来可能是这样的:
(a1, b1, c1), (a1, b2, c2), (a2, b1, c1), ...
索引查找过程
当执行查询时,MySQL会使用索引的最左列来定位到B+树中的正确位置。例如,对于查询WHERE a = X AND b = Y
,MySQL会首先查找所有a = X
的记录,然后在其中查找b = Y
的记录。
为什么是最左前缀
- 索引有序性:由于索引是按照定义的顺序有序存储的,所以只有按照这个顺序来查找,才能保证索引的有效使用。
- 无法跳过前缀列:如果查询条件跳过了复合索引中的某个前缀列,那么MySQL无法利用索引来快速定位到后续列的值。例如,查询
WHERE b = Y
将无法使用(a, b, c)
索引,因为它跳过了列a
。
MyISAM
MyISAM 是 MySQL 中的一个早期存储引擎,它在 MySQL 5.5 及以前版本中被广泛使用。虽然从 MySQL 5.5 开始,InnoDB 成为了默认的存储引擎,但 MyISAM 仍然可以在一些特定场景下使用。
特点
- 非事务性:MyISAM 不支持事务,这意味着它不能提供原子性、一致性、隔离性和持久性(ACID)的保证。如果系统崩溃或断电,可能会丢失数据。
- 表级锁定:当一个查询开始执行时,MyISAM 会对整个表加锁,直到查询完成,不支持行锁。这意味着在执行读取或写入操作时,其他查询必须等待当前操作完成。
- 全文索引支持:MyISAM 支持全文索引,这对于搜索引擎和其他需要全文搜索功能的应用非常有用。
- 压缩选项:MyISAM 表可以通过使用
COMPRESSED
存储选项来压缩,以节省磁盘空间。压缩后的表只能用于 SELECT 查询,因为插入、更新或删除操作会破坏压缩结构。 - 快速读取性能:由于 MyISAM 使用表级锁定和简单的锁定策略,它非常适合大量只读操作的场景。
- 固定大小的行:MyISAM 表中的每一行都有固定的大小,这有助于提高读取性能。
- 支持延迟写入:MyISAM 支持
DELAY_KEY_WRITE
选项,允许延迟索引写入,从而提高写入性能。
索引
- B-Tree 索引:MyISAM 使用 B-Tree 作为主要的索引结构,这是最常见的索引类型。
- 哈希索引:除了 B-Tree 索引之外,MyISAM 还支持哈希索引,但仅限于全文索引和某些非唯一键。
- 空间索引:尽管不是 MyISAM 的强项,但它也可以支持空间索引(R-Tree),不过这个特性在 MyISAM 中并不常用。
文件结构
- 数据文件:每个 MyISAM 表都有一个
.MYD
(MyISAM Data)文件,用于存储表的数据。 - 索引文件:每个表都有一个
.MYI
(MyISAM Index)文件,用于存储索引信息。 - 表定义文件:每个表还有一个
.frm
文件,用于存储表的定义信息。
使用场景
- 数据仓库:MyISAM 适用于数据仓库应用,特别是当数据经常被读取而不是更新的情况下。
- 日志文件:由于其简单的结构和良好的读取性能,MyISAM 也常用于日志记录。
- 静态数据:对于那些数据不经常改变的应用程序,MyISAM 提供了很好的性能。
系统文件层
MySQL的系统文件层(Files and Logs)主要包括存储数据的底层文件,并与上层的存储引擎进行交互,同时也包括文件级别的备份和恢复功能,是文件的物理存储层。
在MySQL的体系架构中,系统文件层位于最下层,直接与操作系统的文件系统进行交互。这一层主要包括日志文件、数据文件、配置文件以及MySQL的相关进程文件,如pid文件和socket文件等。这些文件确保了MySQL数据的持久化和系统的稳定运行。
文件类型
在系统文件层中,MySQL使用多种类型的文件来存储数据和管理数据库:
表结构文件(.frm)
- 存储表的结构定义,包括字段、索引和属性等信息。
- 每个表都有一个对应的.frm文件。
数据文件
- 存储表中的实际数据。
- 不同存储引擎有不同的数据文件格式:
- InnoDB:使用表空间(Tablespaces)来存储数据,通常包括一个或多个.ibd文件(独立表空间)或.ibdata文件(共享表空间)。
- MyISAM:数据文件通常以.MYD(MYData)为扩展名。
索引文件
- 存储表的索引数据。
- 不同存储引擎有不同的索引文件格式:
- InnoDB:索引数据通常存储在.ibd文件中,与数据文件相同。
- MyISAM:索引文件通常以.MYI(MYIndex)为扩展名。
日志文件
- 记录数据库的操作和状态信息,用于故障恢复和数据复制。
- 错误日志(error.log):记录MySQL服务器的启动、运行和关闭过程中的错误信息。
- 二进制日志(binlog):记录所有更改数据的SQL语句,用于数据复制和恢复。
- 慢查询日志(slow_query.log):记录执行时间超过指定阈值的查询。
- 事务日志(InnoDB的redo日志):记录事务操作,用于崩溃恢复。
配置文件
- 存储MySQL服务器的配置设置,如my.cnf或my.ini。
其他文件
- 如临时文件、状态文件、套接字文件等。