☰
MySQL核心机制面试指南:SQL执行流程、索引、事务与锁全解
2026/10/5 7:50:33 网站建设 项目流程

准备后端面试的时候,MySQL基本都是绕不开的重头戏。很多朋友管这叫“八股文”,但我更愿意把它理解为“基本功的骨架”。不管你是学生准备校招,还是工作两三年的开发想查漏补缺,又或者是运维想深入了解原理,把MySQL这套核心知识点吃透,绝对比刷几百道LeetCode更容易在面试中拉开差距。

这套内容我会按照自己梳理的体系来写:先看懂一条SQL从客户端到磁盘的完整旅程,再逐层拆解索引、事务、锁、日志这些核心机制,最后落到真实的调优和面试追问上。整个系列会分多篇,这篇是第一篇,聚焦最基础也最容易被问出深度的部分。

1. 一条SQL的执行流程,藏着面试官最爱追问的MySQL架构

很多人背过“MySQL分为Server层和存储引擎层”,但面试官只要多问一句“这两层具体怎么协作的”,就直接卡壳。其实MySQL的架构非常好记,只需要抓住一条主线:一条SQL从客户端发过来,到真正操作磁盘上的数据,依次经过哪些环节。

1.1 连接层与服务层:你的SQL在这里被“翻译”成可执行的计划

第一条必经之路是连接管理。客户端通过TCP协议连接到MySQL,服务端会有专门的线程来处理这个连接。这里有个容易忽略的细节:连接本身有超时时间,默认是8小时(wait_timeout参数),如果超过这个时间没有活动,服务端会主动断开。我之前就遇到过半夜的定时任务因为连接被MySQL掐断而报错的情况,排查到最后就是这里的问题。

连接建立之后,SQL会进入查询缓存(Query Cache)。不过在MySQL 8.0里这个缓存已经被彻底移除了,因为它的命中率实在太低,而且每次表数据更新都要清掉对应的缓存,维护成本远大于收益。如果你用的还是5.7版本,我建议直接把query_cache_type设为OFF,省得白费力气。缓存没命中的话,SQL就进入分析器,先做词法分析(把SQL拆成一个个关键字、表名、列名),再做语法分析(检查SQL是否符合MySQL的语法规则)。注意这里有个非常基础的坑:表名和字段名不存在,并不是在分析器发现的,而是在优化器阶段才报错。

1.2 优化器与执行器:为什么有时候“明明有索引却没用上”

分析完之后,优化器会决定这条SQL“用哪种方式执行最高效”。比如关联查询是先查A表还是先查B表,多个索引同时存在时用哪个索引。优化器并不是万能的,它的判断依据是统计信息(索引的基数、区分度)。我遇到过一种经典情况:一张表只有几万行数据,但状态字段上有个索引,优化器一算觉得直接全表扫描比走索引再回表更快,于是索引就“失效”了。这不是索引本身的问题,而是优化器的成本估算逻辑所决定的。遇到这种场景,我们通常用FORCE INDEX来强制走索引,但前提是你确实评估过两种方案的实际耗时。

执行器是真正干活的人。它会先判断你对这张表有没有操作权限(这一步在MySQL 8.0之前是在分析器阶段做的),然后调用存储引擎的接口,一行一行地拿数据、判断条件、返回结果。慢查询日志里记录的执行时间,就是从进入执行器之后开始算的,不包含前面的连接、分析和优化时间。

1.3 存储引擎层:InnoDB为什么是默认选择

存储引擎层负责真正跟磁盘打交道。MySQL 5.5.5之后默认引擎就是InnoDB,它支持事务、行级锁、崩溃恢复,这些特性基本覆盖了绝大多数业务场景。MyISAM虽然查询速度快、占用空间小,但一不支持事务,二只支持表级锁,三崩溃后无法安全恢复,除了某些只读报表场景,基本没有理由再去用它。

这里有个面试官很爱问的切入点:一条UPDATE语句的执行流程,可以串起InnoDB的核心机制,包括Buffer Pool、redo log、undo log和binlog的协作。这个我会在后面日志部分展开,但你可以先记住这条主线:更新时,先看数据页在不在Buffer Pool里,不在就从磁盘加载;然后写undo log用于回滚,再更新Buffer Pool中的内存页,接着写redo log(状态为prepare),最后写binlog并提交事务,redo log再改为commit状态。

2. InnoDB索引:从B+树到回表,一次讲透底层原理

索引是MySQL面试的重灾区,而且问得越来越细。以前问“索引有哪些类型”,现在直接问你“为什么InnoDB用B+树而不用B树”甚至“为什么不用哈希索引”。如果只是背结论,很容易被追问到破绽。

2.1 为什么偏偏是B+树

先看哈希索引。它确实快,等值查询O(1)级别,但两个致命弱点是无法排序、无法范围查询。范围查询是业务里最普遍的需求,比如按时间查订单、按价格查商品,哈希索引完全做不了。

再看二叉搜索树。极端情况下会退化成链表,高度不可控。红黑树解决了一部分平衡问题,但树的高度依然太高。我们算一笔账:假设一张表有1000万行数据,用红黑树存储,树的高度大约是log2(1000万)≈24层。每层都是一次磁盘IO,加载索引节点和叶子节点需要约2到3次IO,查询一条数据可能就要24次磁盘IO,这在实际生产中完全不可接受。

B+树之所以胜出,在于“矮胖”二字。B+树的非叶子节点只存索引键值,不存数据,因此单个节点能容纳更多的子节点指针。以MySQL默认的16KB数据页为例,假设索引键是8字节的bigint,指针约6字节,那么一个节点能存储约16KB/14B≈1170个键值对。一个三层的B+树就能存放约1170×1170×16(每个叶子页按16条数据估算)≈2000多万条记录。也就是说,2000万行的表,查询任一数据最多只需要3次磁盘IO,这性能是非常可观的。

面试官如果追问“既然非叶子节点不存数据,那B树和B+树的区别是什么”,你可以从三个角度回答:一是叶子节点是否存数据(B树所有节点都存,B+树只有叶子节点存);二是叶子节点是否形成链表(B+树的叶子节点用双向链表串联,方便范围查询和排序);三是IO次数(B+树非叶子节点更小,单次IO能加载更多索引键,树更矮)。之前见过一个压轴问题:为什么B+树的叶子节点要设计成双向链表,而不是单向链表?答案是为了支持倒序扫描和更方便的页内数据移动,这个细节能直接区分有没有深入读过源码。

2.2 聚簇索引、二级索引与回表

InnoDB的数据存储方式决定了它的索引结构:表本身按主键构建B+树,叶子节点存放整行数据,这叫聚簇索引(也叫主键索引)。其他索引统称二级索引,二级索引的叶子节点存放的是主键值,而不是数据行地址。

这里延伸出一个关键知识点:回表。如果SQL走的是二级索引,MySQL会先在二级索引B+树里找到匹配的主键值,再到聚簇索引里查完整数据行。这个过程叫回表。回表意味着一次查询至少两次索引扫描,所以我们在设计索引时都希望尽量覆盖查询。

举个例子,假设你有张用户表t_user(id, name, age, phone),在上面建了idx_name(name)。执行SELECT id, name FROM t_user WHERE name = '张三'时,二级索引的叶子节点已经有id和name,不需要回表,这就是覆盖索引。但如果你改成SELECT id, name, age FROM t_user WHERE name = '张三',age字段不在索引里,就必须回表取整行数据。这里的优化思路很简单:把经常要查询的字段加到索引里,比如改成idx_name_age(name, age),查询就不用回表了。

2.3 最左前缀原则和索引失效的常见场景

联合索引(复合索引)面试必问“最左前缀原则”。它的本质是B+树对多个字段按顺序排序:先按第一个字段排序,第一个字段相同再按第二个字段排序。因此查询条件只要包含了联合索引的最左字段,就有机会走索引;如果跳过了最左字段直接查第二个字段,这个联合索引就帮不上忙了。

那么哪些写法会导致索引失效?我整理过一份自查清单:

  • 对索引列做了函数操作或隐式类型转换,比如WHERE DATE(create_time) = '2025-01-01'或者WHERE phone = 13800138000(phone是varchar但没加引号)。
  • 使用LIKE '%关键字'这种前置模糊匹配,因为B+树无法根据前导通配符定位。
  • 联合索引中不满足最左前缀。
  • 优化器判断走索引成本高于直接扫全表(比如区分度极低的字段)。
  • 使用OR连接时,如果其中一个条件不是索引列,MySQL可能放弃索引转全表扫。实际上这个不能一概而论,MySQL 8.0的优化器能力比5.7强不少,有时也会对OR条件做索引合并,但依赖它不如自己写对SQL靠谱。

提示:判断一条SQL到底有没有走索引,别猜,直接看执行计划。EXPLAIN SELECT ...,key字段是实际用的索引,rows是预估扫描行数,Extra里出现Using index说明是覆盖索引,出现Using filesort说明排序没用上索引。

3. 事务隔离级别与MVCC,理解并发控制的真正核心

事务这一块,光背“ACID”四个字母是不够的。面试官通常会顺着往下问“InnoDB怎么保证原子性和持久性的”“可重复读是怎么实现的”。这两个问题的答案,都要落到redo log、undo log和MVCC上面。

3.1 事务的四大特性分别靠什么保证

原子性靠undo log。事务执行过程中,每条数据变更之前,都会先把旧值写入undo log。如果事务回滚,InnoDB通过undo log把数据恢复到变更前的状态。一致性是终极目标,靠约束、外键和应用逻辑保证。隔离性靠锁和MVCC。持久性靠redo log,而且这里有两个关键细节:一是redo log是物理日志,记录的是“页的修改”,而不是“执行的SQL”;二是事务提交时,redo log会刷盘(innodb_flush_log_at_trx_commit默认1,每次提交都刷),保证即使MySQL崩溃重启,也可以通过重放redo log恢复数据。

面试里一个经典的扩展问题是“如果redo log写满了怎么办”。这涉及redo log的循环写机制:它的大小是固定的(由innodb_log_file_size控制),写完一圈会覆盖旧日志。在覆盖之前,InnoDB会触发一次checkpoint,把Buffer Pool里对应的脏页刷到磁盘。如果checkpoint来不及完成而redo log又被写满,MySQL就会阻塞写操作,直到刷盘进度跟上。

3.2 四种隔离级别与三类数据问题

SQL标准的四种隔离级别,从宽松到严格分别是:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)。

每种隔离级别解决了什么问题,又留下了什么问题:

  • 读未提交:允许读到其他事务未提交的变化,存在脏读。
  • 读已提交:只允许读到已提交的变化,解决了脏读,但存在不可重复读(同一个事务里两次读取结果不同)。
  • 可重复读:同一个事务里多次读取结果一致,解决了不可重复读,但存在幻读(同一个事务里两次查询返回的记录数不同)。
  • 串行化:事务串行执行,彻底解决幻读,但并发能力几乎为零。

MySQL默认隔离级别是可重复读,并且InnoDB在可重复读级别下通过“当前读”加锁+MVCC快照读的组合,基本解决了幻读问题。注意我说的是“基本”,因为如果事务A先快照读了一次,事务B插入了新数据并提交,你再在事务A里执行UPDATE或SELECT ... FOR UPDATE这种当前读,依然可能读到新插入的行。这也是网上很多文章争论“InnoDB到底有没有彻底解决幻读”的根源。

3.3 MVCC的含义:版本链、ReadView与可见性判断

MVCC(Multi-Version Concurrency Control,多版本并发控制)是InnoDB实现隔离级别的核心机制。每行数据都有两个隐藏字段:trx_id表示最近一次修改这行数据的事务ID,roll_pointer指向undo log中该行的上一个版本。这样一行数据在多个事务的修改下,通过undo log连成了一条版本链,每条链上的节点都带有所属事务ID。

ReadView是MVCC判断“哪个版本可见”的基准。它主要包含四部分信息:创建这个ReadView的事务ID、当前活跃(未提交)事务ID列表、活跃事务列表的最小ID、以及下一个分配的ID。判断规则简化为三句话:

  • 如果版本的事务ID等于创建ReadView的事务ID,说明是当前事务自己修改的,可见。
  • 如果版本的事务ID小于最小活跃ID,说明事务已提交,可见。
  • 如果版本的事务ID大于或等于下一个分配ID,说明是未来事务,不可见。
  • 如果版本的事务ID落在活跃列表中,说明事务还未提交,不可见。

“可重复读”与“读已提交”的区别,在于生成ReadView的时机。读已提交是每次SELECT都生成一个新的ReadView,所以能看到其他事务新提交的数据,产生不可重复读;可重复读是事务内第一次SELECT生成ReadView,之后的SELECT都复用同一个,所以整个事务期间看到的快照永远一致。这是解释两种隔离级别差异最直观的切入点。

注意:MVCC只对普通的快照读(也就是非锁定读的SELECT)生效。加锁的当前读(SELECT ... FOR UPDATE、UPDATE、DELETE)是不走MVCC的,它们走的是另外一套锁机制。

4. 锁机制:从全局锁到行锁,梳理真实的加锁过程

锁相关的面试题,问法五花八门:“MySQL锁的分类”“间隙锁是什么”“死锁怎么排查”。想完全掌握,得有清晰的层级结构:从全局锁到表级锁,再到InnoDB的行级锁。

4.1 全局锁与表级锁:什么时候用、有什么代价

全局锁的典型操作是FLUSH TABLES WITH READ LOCK,它让整个库变成只读状态。这种操作一般只用于全库备份等场景,代价是业务全部停写。网上更推荐的方式是使用mysqldump --single-transaction,利用InnoDB的MVCC机制做一致性备份,整个过程不影响业务写入。

表级锁包含表锁(LOCK TABLE ... READ/WRITE)和元数据锁(MDL锁)。MDL锁是MySQL在访问表时自动加的,分为MDL读锁和MDL写锁。这里有一个特别容易被忽略的线上事故场景:一个DDL操作在修改表结构时持有MDL写锁,如果这个DDL一直没执行完,就会阻塞后面所有的读写请求,再叠加连接池耗尽,整个服务就假死了。解决思路通常是把大表DDL放到低峰期,或者使用工具(比如gh-ost、pt-online-schema-change)做在线表结构变更。

4.2 行级锁与Record Lock、Gap Lock、Next-Key Lock

InnoDB的行锁是真正细粒度的锁,而且锁的是索引记录,不是行数据本身。执行SELECT ... FOR UPDATE、UPDATE、DELETE时,InnoDB会按实际扫描到的索引记录加锁。

行级锁主要有三种:记录锁(Record Lock)锁定单条索引记录;间隙锁(Gap Lock)锁定一个开区间范围,防止其他事务在这个区间插入数据;临键锁(Next-Key Lock)是记录锁和间隙锁的组合,锁定的范围是前开后闭区间。可重复读隔离级别下,InnoDB默认使用临键锁,这也是它能防止幻读的加锁层面保证。

这里有个非常经典的问题:“在可重复读隔离级别下,执行SELECT * FROM t_user WHERE age > 20 FOR UPDATE,会锁什么范围?”答案是把age索引上大于20的所有记录,以及20到正无穷之间的间隙全部锁住。这意味着其他事务在age>20的范围里插不了任何数据,包括不存在的记录。理解这个之后,你就能明白为什么高并发写入场景下,一次不加条件或者条件过宽的FOR UPDATE查询可以把整张表卡死。

4.3 锁冲突、死锁与排查手段

死锁的本质是两个或多个事务循环等待对方的锁。在MySQL里最常见的死锁场景是:事务A先更新了表1的记录1,再更新表2的记录2;事务B以相反顺序更新同样的两条记录,互相等锁,谁也无法提交。

排查死锁的步骤我非常建议背下来:

  • 使用SHOW ENGINE INNODB STATUS查看最近一次死锁的详细信息,日志里会清楚记录两个事务各持有哪些锁、在等待哪个锁。
  • 如果死锁频繁,打开innodb_print_all_deadlocks参数,把所有死锁信息输出到错误日志。
  • 分析死锁信息,重点检查业务侧的加锁顺序是否一致,尽量让所有事务以相同顺序访问表和行。
  • 无法避免的死锁,在业务代码里捕获死锁异常(错误码1213)并重试。

提示:死锁不一定是MySQL配置问题,更多的是应用层并发设计问题。大多数死锁可以通过统一加锁顺序、缩短事务时间、减少锁范围来规避。

4.4 乐观锁和悲观锁怎么选

这也是面试高频题。悲观锁是数据库层面的锁,比如上面提到的SELECT ... FOR UPDATE,先锁住数据再操作,适合并发竞争激烈的场景。乐观锁不靠数据库锁,而是通过版本号或时间戳实现:每次更新时比较版本号,如果版本变了,说明数据被改过,更新失败,需要重试。举个典型例子:

-- 乐观锁更新:version作为版本号 UPDATE t_goods SET stock = stock - 1, version = version + 1 WHERE id = 123 AND version = 3;

如果affected rows为0,说明版本号不匹配,其他事务已经改过这行,业务层需要重新加载数据再尝试。

乐观锁适合读多写少、冲突概率低的场景,比如论坛帖子的浏览量累加、点赞数更新。但如果冲突频繁,乐观锁会导致大量重试,性能反而不如悲观锁。另外注意一点:UPDATE语句本身在InnoDB中执行时就会对命中的记录加行锁,所以即使你代码里没写FOR UPDATE,一条UPDATE也已经是“悲观”的。

5. redo log、undo log 与 binlog:三条日志的协作关系

日志系统是MySQL面试的深水区,但也是最能体现一个候选人对数据库理解深度的地方。我见过很多人能背出“两阶段提交”这个名词,但完全说不清楚为什么需要“两阶段”,更说不清楚redo log和binlog到底有什么区别。

5.1 三条日志各自扮演的角色

redo log是InnoDB存储引擎特有的物理日志,记录“数据页做了什么修改”,用于崩溃恢复。它的大小固定,采用循环写的方式。binlog是MySQL Server层的逻辑日志,记录的是SQL语句的“逻辑操作”或“行级别变更”,比如“在某个时间点,把某一行从A改成B”。它用于主从复制、数据恢复,并且是追加写,不会覆盖。undo log则是逻辑日志,记录数据修改前的状态,用于事务回滚和MVCC版本链构建。

区分这三者有一个简单口诀:redo log是“存储引擎层面的物理日志,管崩溃恢复”,binlog是“Server层面的逻辑日志,管主从复制和数据归档”,undo log是“逻辑日志,管回滚和读快照”。

5.2 为什么必须有“两阶段提交”

如果redo log和binlog是分别独立写入的,那么崩溃就可能在两步之间发生,导致两份日志不一致。举个例子:如果先写redo log后写binlog,redo log写入后MySQL崩溃,binlog没来得及写,从库通过binlog同步的数据就会少一条;如果先写binlog后写redo log,binlog写入后崩溃,主库通过redo log恢复了这条更新,但从库没有收到对应binlog,主从数据就不一致了。

InnoDB的解决方案是“两阶段提交”:

  • 第一阶段:事务执行过程中不断写redo log,但状态是prepare。
  • 第二阶段:事务提交时先写binlog,然后把redo log的状态更新为commit。

只有在redo log的prepare和binlog都成功写入后,事务才算真正提交。如果崩溃发生在写binlog之前,事务回滚;如果发生在写binlog之后、redo log标记commit之前,崩溃恢复时MySQL会对比两份日志,发现binlog已写入而redo log处于prepare,会认为事务有效并完成提交。这样主从数据就不可能出现不一致的情况。

5.3 更新语句在InnoDB中到底发生了哪些事

拿最简单的示例来说:

UPDATE t_user SET age = 18 WHERE id = 1;

假定id=1这行数据一开始age=20。这条SQL在InnoDB内部大概要走这几步:

  1. 加载数据页:如果id=1所在的数据页不在Buffer Pool里,先从磁盘读入内存。
  2. 写入undo log:在修改前,把旧值(age=20)连同相关事务信息记录到undo log。
  3. 修改内存:更新Buffer Pool中该数据页的age为18。
  4. 写redo log(prepare):记录物理变更,状态为prepare。
  5. 写binlog:记录这条UPDATE的逻辑操作。
  6. 提交事务:redo log状态改为commit,事务完成。

注意第三步和第四步的顺序:数据修改先发生在内存里,事务提交时并不要求把脏页立刻刷到磁盘。这就是WAL(Write-Ahead Logging,预写日志)机制的精髓:先写日志、后刷数据。MySQL宕机后,优先用redo log恢复内存中尚未落盘的数据页,而不是逐页去扫描所有磁盘数据,这样既保证了持久性,也避免了频繁的随机磁盘写。

6. 高频追问与实用避坑:面试里最容易答偏的几个问题

写到这里,基础的核心机制都过了一遍。最后我再把自己在面试别人和被人面试过程中遇到的几个高频追问,整理成速查,不一定按标准答案的方向走,但都是实操中踩出来的经验。

6.1 为什么主键推荐自增整数,而不是UUID

这个问题表面是问“数据类型选择”,深层其实是“索引维护与页分裂”的原理。InnoDB的聚簇索引按主键有序排列,自增id插入时永远追加到B+树的最后,顺序写入效率极高。UUID是完全随机的字符串,插入时像无头苍蝇一样随机落在B+树的各个位置,会导致频繁的页分裂、页碎片化,并且聚簇索引体积远大于bigint,二级索引的叶子节点也会变大,直接拖垮写入性能和缓存命中率。

还有更隐蔽的一点:id的生成不一定要依赖数据库的自增。高并发下可以用雪花算法生成趋势递增的id,既能保持分布式系统的唯一性,又不会破坏B+树的有序插入特性。

6.2SELECT COUNT(*)很慢,为什么不用COUNT(1)和COUNT(字段)替代

这个问题至少有一半人答错。InnoDB里COUNT(*)和COUNT(1)的性能几乎没有区别,因为它俩都只统计行数,不需要关注具体的值。真正慢的场景是在大数据量表上毫无条件地COUNT(*),本质是需要在聚簇索引上扫描,没有捷径。

如果业务上经常需要精确统计行数,我一般推荐两种方案:一是使用单独的统计表,在业务逻辑里维护一个计数器,每次增删改都更新;二是针对只读报表场景,用汇总表或者物化视图来异步聚合。还有人会遇到“为什么COUNT(id)走了二级索引还是慢”的问题——其实二级索引的叶子节点只存主键值,比聚簇索引叶子节点小很多,所以COUNT走二级索引比走主键索引更快。因此InnoDB的COUNT(*)优化器通常也会自动选择一个最小的二级索引来扫描,而不是主键索引。

6.3 一条SQL慢,优先排查的方向是什么

这个实操问题,面试里也常被当作开放性追问。我自己的排查顺序是:

  • 先看EXPLAIN执行计划,确认是否走了合适的索引、有没有全表扫描、有没有filesort和temporary表。
  • 再看慢查询日志,确认SQL执行的精确耗时和数据扫描行数。
  • 看这条SQL对应表的行数、索引区分度、数据分布,判断是索引设计问题还是SQL写法问题。
  • 如果单条SQL本身没问题,那就排查是不是并发冲击、锁等待或IO瓶颈。

一个很容易踩的坑是:即使SQL走了索引,也可能慢。因为InnoDB的最小IO单位是数据页(16KB),如果要查询的数据分布在很多不同的页上,即使每条记录只用几字节,也需要读取很多个页。这就解释了为什么“大字段全查”比“索引覆盖查询”慢得多,也解释了为什么好的表设计要避免过宽的字段,尽量把大文本字段拆到单独的表里。

6.4 常用运维与调试命令速查

虽然这是偏开发向的八股文,但有些命令在面试中经常被提到“你会怎么做”,这里一并分享出来:

  • EXPLAIN:分析执行计划,最常用的调优工具,注意它的Select_type、type、key、rows、Extra每一列的含义。
  • SHOW CREATE TABLE table_name:查看表结构的完整定义,包括索引、约束、字符集。
  • SHOW INDEX FROM table_name:查看索引的基数、区分度和索引列顺序。
  • SHOW PROCESSLIST:查看当前所有连接及正在执行的SQL,排查慢SQL和锁等待非常有效。
  • SHOW ENGINE INNODB STATUS:查看InnoDB状态,包括事务、锁等待、死锁信息、Buffer Pool命中率等。
  • OPTIMIZE TABLE table_name:整理表的碎片空间,但对大表操作要谨慎,建议使用pt-online-schema-change这类在线工具。

写在最后的个人心得

我自己在面试前端和后端工程师的时候,很少直接问“索引失效的场景有哪些”这种记忆型问题,更多是给一个真实业务场景,让对方判断“这条SQL该怎么建索引”“这是该怎么设计隔离级别”。因为只有理解了底层原理,才能在业务中做出正确选型。

MySQL这套体系学起来特别适合“由点成面”:从一条SQL的执行流程出发,串出连接器、优化器、执行器、存储引擎;从一条UPDATE出发,串出Buffer Pool、undo log、redo log、binlog、两阶段提交;从一次并发读写冲突出发,串出MVCC、锁、隔离级别。每一环都是下一环的铺垫,整张知识网拉通之后,你再去看面试题,基本不会觉得是八股文了,更像是常识。

下一篇我会继续整理MySQL性能调优与高可用方向的内容,包括线上慢SQL分析全流程、主从复制原理与GTID模式、大表结构变更的在线DDL方案、以及压测和优化工具集锦。这些东西光靠一篇肯定写不完,但核心思路是一致的:先懂原理,再谈优化,不要上来就改参数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询