目录
server层
连接器:
查询缓存:
分析器:
优化器:
执行器:
存储引擎层:
该层主要包括Innodb底层原理与Mysql日志机制
redo log
redo log 写入磁盘过程分析
bin log
Binlog 关键参数:
binlog 的日志格式
binlog写入磁盘机制
undo log
Undo Log 关键参数:
Undo Log 工作过程分析:
Undo Log 的两大作用:
slow query log
Slow Query Log 关键参数:
Slow Query Log分析流程:
error log
Error Log 关键参数:
Error Log 记录内容:
mysq可以分为server层和存储引擎层
Server层:主要包括连接器、查询缓存、分析器、优化器、执行器、写Binlog等,涵盖 MySQL 的大多数核心服务功能,以及所有的内
置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
存储引擎层:存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引
擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。也就是说如果我们在
create table时不指定表的存储引擎类型,默认会给你设置存储引擎为InnoDB。
server层的连接器、查询缓存、分析器、优化器、执行器干了什么?
server层
连接器:
看名字就知道,就是用来连接数据库的,比如你连接数据库,当然也可以是可视化工具连接数据库,比如navicat、DataGrip等。
命令通常是这样写的:
mysql ‐h host[数据库地址] ‐u root[用户] ‐p root[密码] ‐P 3306连接命令中的 mysql 是客户端工具,用来跟服务端建立连接。在完成经典的 TCP 握手后,连接器就要开始认证
你的身份,这个时候用的就是你输入的用户名和密码。
1、如果用户名或密码不对,你就会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
2、如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此
时读到的权限。
这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在
连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。
查询缓存:
mysql 8.0已经移除了查询缓存功能
查询缓存就是,你以前查过的内容,mysql都有记录,当你再次输入查询语句时候,mysql不会直接执行查询语句,会先从查询缓存中查找这个语句,如果有,那就直接返回,没有再往下执行,然后该次查询语句和返回的值又会保存到查询缓存中。
虽然命中了,可以让查询效率大大提高,不过基本没用,因为只要这个表执行了update,那么就会清空这个表的查询缓存,可以在静态表中这么操作,就是不太常更新的表。
分析器:
分析器主要做两个操作,词法分析和语法分析
词法分析:sql语句是由空格和字符串组成,你输入后,mysql就需要识别这些字符串是干嘛的,比如select语句,mysql识别到了select,那么这就是有一条查询语句,select clum from tablename,分析完selecet后,就会分析tablename,mysql就会直接把tablename识别成表tablename,把字符串clum识别成列id。
语法分析:词法分析完后,会通过语法分析判断你输入的这条语句是否正确。不正确就会返回:“You have an error in your SQL syntax”。
优化器:
经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各
个表的连接顺序;以及一些mysql自己内部的优化机制。
优化器主要解决三个核心问题:
1.选哪个索引?
- 如果一个表有 `age` 索引、`name` 索引等多个索引,优化器会根据统计信息(比如 `age>18` 大概有多少行)选择一个它认为最快的索引。
- 有时它可能会觉得全表扫描比用某个索引更快,那它就不用索引。
2.多表连接(JOIN)以什么顺序执行?
- 比如 `SELECT * FROM A JOIN B ON A.id = B.id`。
- 先查 A 再匹配 B,还是先查 B 再匹配 A?不同顺序的中间结果大小可能相差成千上万倍。
- 优化器会估算各种顺序的成本,选择连接代价最小的顺序。
3.内部重写与优化
- 比如把 `WHERE 1=1 AND age>18` 简化为 `WHERE age>18`。
- 把子查询改写成 JOIN(如果合适)。
- 常量提前计算(如 `WHERE id = 1+2` 变成 `WHERE id = 3`)。
- 关联列类型不一致时隐式转换(虽然这不一定是好事)。
执行器:
开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如
下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证)。
如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口,比如使用InnerDB的接口。
存储引擎层:
该层主要包括Innodb底层原理与Mysql日志机制
Innodb底层原理:
InnoDB是MySQL默认的事务型存储引擎,采用多版本并发控制(MVCC)机制实现高并发。底层基于B+树索引结构组织数据,所有数据存储在聚簇索引中,非主键索引(二级索引)的叶子节点存储主键值而非数据指针。InnoDB通过缓冲池(Buffer Pool)机制缓存热点数据页,减少磁盘I/O。
事务支持通过undo日志实现回滚操作,redo日志保证事务持久性。采用两阶段锁定协议(2PL)和间隙锁(Next-Key Locking)解决幻读问题。自动死锁检测机制通过等待图(wait-for graph)识别并回滚代价较小的事务。
Mysql日志机制:
redo log(重做日志)物理日志,记录页面的物理修改操作。采用循环写入方式,实现崩溃恢复时的数据重放。通过innodb_flush_log_at_trx_commit参数控制刷盘策略,平衡性能与安全性。
undo log(回滚日志)逻辑日志,存储事务修改前的数据镜像。支持事务回滚和MVCC机制,通过回滚段(Rollback Segment)管理。长事务会导致undo日志堆积,可能引发空间膨胀。
binlog(二进制日志)Server层逻辑日志,记录所有更改数据的SQL语句。用于主从复制和数据恢复,支持STATEMENT/ROW/MIXED三种格式。通过sync_binlog参数控制刷盘频率。
slow query log(慢查询日志)记录执行时间超过long_query_time阈值的SQL语句,需手动开启。用于性能分析和SQL优化,可通过mysqldumpslow工具分析日志内容。
error log(错误日志)记录服务器启动、运行、关闭过程中的警告和错误信息。默认存放在数据目录下,文件名为hostname.err,包含关键故障诊断信息。
redo log
redo log重做日志关键参数:
innodb_log_buffer_size:设置redo log buffer大小参数,默认16M ,最大值是4096M,最小值为1M。
innodb_log_group_home_dir:设置redo log文件存储位置参数,默认值为"./",即innodb数据文件存储位置,其中的 ib_logfile0 和 ib_logfile1 即为redo log文件。
innodb_log_files_in_group:设置redo log文件的个数,命名方式如: ib_logfile0,iblogfile1... iblogfileN。默认2个,最大100个。
innodb_log_file_size:设置单个redo log文件大小,默认值为48M。最大值为512G,注意最大值指的是整个 redo log系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size)不能大于最大值512G。
innodb_flush_log_at_trx_commit:这个参数控制 redo log 的写入策略,它有三种可能取值
设置为0:表示每次事务提交时都只是把 redo log 留在 redo log buffer 中,数据库宕机可能会丢失数据。
设置为1(默认值):表示每次事务提交时都将 redo log 直接持久化到磁盘,数据最安全,不会因为数据库宕机丢失数据,但是效率稍微差一点,线上系统推荐这个设置。
设置为2:表示每次事务提交时都只是把 redo log 写到操作系统的缓存page cache里,这种情况如果数据库宕机是不会丢失数据的,但是操作系统如果宕机了,page cache里的数据还没来得及写入磁盘文件的话就会丢失数据。
redo log 写入磁盘过程分析
redo log写入磁盘的操作,相当于一个环形链表,然后有两个指针,一个check point,一个write pos。如下图所示:
Write Pos (写入位置):
指向当前写入日志的末尾。
随着数据库执行写操作,它会不断向后移动(每次写入新的 Redo Log 记录)。
Check Point (检查点):
指向当前要擦除/覆盖的位置。
代表这个位置之前的日志记录所对应的脏页,已经成功落盘(写到了
.ibd数据文件中)。因此这些日志就没用了,可以被覆盖。
环形链表的工作逻辑
正常运行:Write Pos 追着 Check Point 跑,两者之间的空隙就是“空闲区域”,可以写入新日志。
写满的情况:如果 Write Pos 追上了 Check Point,意味着环形队列满了。此时 MySQL 会被阻塞(不能写数据了),强制推进 Check Point(将对应脏页刷盘),清出空闲空间,然后继续写。
bin log
bin log二进制归档日志
Binlog 关键参数:
| 参数 | 作用 | 推荐值 |
|---|---|---|
log_bin | 开启 Binlog 功能 | ON/mysql-bin |
binlog_format | Binlog 记录格式 | ROW(MySQL 8.0 默认) |
sync_binlog | 控制 Binlog 刷盘时机 | 1(最安全) |
binlog_cache_size | 事务未提交前 Binlog 缓存大小 | 32KB~2MB |
max_binlog_size | 单个 Binlog 文件最大大小 | 1GB |
expire_logs_days/binlog_expire_logs_seconds | Binlog 自动清理时间 | 7 ~ 30 天 |
binlog 的日志格式
| 格式 | 记录内容 | 适用场景 |
|---|---|---|
STATEMENT | SQL 语句原文 | 日志量小,但有主从不一致风险 |
ROW | 每行数据的变更前后值 | 主从一致,推荐使用 |
MIXED | MySQL 自动选择 | 兼容模式 |
binlog写入磁盘机制
刷盘时机(sync_binlog 参数):
| 参数值 | 行为 |
|---|---|
0 | 写入 OS 缓存,由操作系统决定刷盘(性能最高,可能丢数据) |
1 | 每次事务提交都立即刷盘(最安全,推荐) |
N(如 100) | 每 N 个事务提交后刷一次盘(折中方案) |
binlog日志文件恢复数据
undo log
Undo Log 关键参数:
| 参数 | 作用 |
|---|---|
innodb_undo_tablespaces | Undo 表空间数量 |
innodb_undo_log_truncate | 是否自动截断 Undo 日志 |
innodb_max_undo_log_size | Undo 表空间最大大小 |
innodb_undo_logs/innodb_rollback_segments | 回滚段数量(默认 128) |
Undo Log 工作过程分析:
Undo Log 的两大作用:
事务回滚:事务执行失败时,用 Undo 里的旧值覆盖回去
MVCC 多版本并发控制:为读视图提供不同版本的数据快照
slow query log
Slow Query Log 关键参数:
| 参数 | 作用 | 推荐值 |
|---|---|---|
slow_query_log | 开启慢查询日志 | ON |
slow_query_log_file | 慢查询日志文件路径 | /var/log/mysql/slow.log |
long_query_time | 慢查询阈值(秒) | 1或0.5 |
log_queries_not_using_indexes | 记录未走索引的查询 | ON |
log_slow_admin_statements | 记录慢的管理语句 | ON |
min_examined_row_limit | 扫描行数下限 | 可设 1000 |
Slow Query Log分析流程:
error log
Error Log 关键参数:
| 参数 | 作用 |
|---|---|
log_error | 错误日志文件路径 |
log_warnings/log_error_verbosity | 日志详细程度(1=错误,2=警告+错误) |
log_error_services | 错误日志服务组件(MySQL 8.0+) |
Error Log 记录内容:
| 内容类型 | 说明 |
|---|---|
| 启动/关闭信息 | 服务启动、停止的时间及状态 |
| 严重错误 | 表损坏、InnoDB 崩溃、死锁等 |
| 连接错误 | 连接超时、权限拒绝等 |
| 警告信息 | 主从复制警告、配置不合理警告 |