[PAI严选]第二弹:mysql篇

Carlos 发布于 6 天前 28 次阅读


第一板块:SQL 调优与索引底层(日常开发必考)

1:怎么解决 MySQL 的深分页(超大分页)问题?

“超大分页通常发生在数据量极大的情况下,如果直接使用 LIMIT 1000000, 10 并且带排序,MySQL 会查出前一百万零十条数据,然后丢弃前面的,效率极低。

我们的解决方案是:子查询 + 覆盖索引(延迟关联)。

首先,通过覆盖索引快速查出目标分页的 ID 列表(因为只查 ID,不查整行,所以不用回表,速度极快);然后再用这些 ID 作为条件,通过子查询或 JOIN 回表去查出真正需要的数据行。这样极大地减少了回表的次数,提升了查询效率。”

2:索引的创建原则有哪些?

[满分回答]:

“我们在建索引时主要遵循以下几个原则:

  1. 看数据量:表数据量超过 10 万以上才考虑建索引,太少没必要。
  2. 看高频词:选择查询条件(WHERE)、排序(ORDER BY)、分组(GROUP BY)最频繁的字段。
  3. 白嫖‘覆盖索引’:尽量使用联合(复合)索引,把 SELECT 需要的字段全包进去,避免回表。
  4. 看区分度:区分度高的字段放联合索引前面,区分度不高的(比如性别)放后面。
  5. 前缀索引:对于内容极长的文本字段,只给前面的几十个字符建前缀索引,省空间。
  6. 克制:严格控制单表索引数量,因为索引本质是 B+ 树,建多了会严重拖慢 INSERT 和 UPDATE 的速度。”

3:什么情况下索引会失效?

[满分回答]:

“常见的踩坑场景有这四个:

  1. 没守规矩:没有遵循联合索引的‘最左匹配原则’。
  2. 开头模糊:使用了 LIKE 模糊查询,且 % 放在了最前面(比如 LIKE '%abc',这就没法走字典序了)。
  3. 字段加工:在索引字段上进行了数学运算,或者隐式的类型转换(比如把字符串当数字查)。
  4. 范围截断:在联合索引中,如果中间某个字段使用了范围查询(比如 >, <),会导致它右边所有字段的索引全部失效。”

4:总结一下你们团队做 MySQL 性能优化的核心思路?(为你补充的问题)

[满分回答]:

“我们的调优口诀分五步:

  1. 省空间:精选字段类型,能用 TINYINT 不用 INT,让 B+ 树更胖、层级更低。
  2. 做目录:精准建立索引,利用 B+ 树的双向链表空降定位。
  3. 少折腾:坚决不写 SELECT * 避免回表;用 UNION ALL 替代 UNION 拒绝无谓的内部排序。
  4. 搞分工:引入读写分离,主库负责写,从库负责读。
  5. 拆大表:当单表过载(超过千万级)时,进行分库分表,把高耸的 B+ 树强行压矮。”

第二板块:事务、锁与底层日志(内功深度必考)

5:事务的特性(ACID)是什么?可以详细说一下吗?

[满分回答]:

“事务的特性是 ACID,以 A 向 B 转账 500 元为例:

  • 原子性 (Atomicity):这 500 块钱的扣除和增加,要么一起成功,要么一起失败,绝不拖泥带水。
  • 一致性 (Consistency):转账前后,总金额数据要守恒。A 扣了 500,B 必须刚好增加 500。
  • 隔离性 (Isolation):A 转账给 B 的过程中,不受 C 给 A 转账等其他并发事务的干扰。
  • 持久性 (Durability):一旦转账提交成功,数据就被永久写在硬盘上了,哪怕下一秒拔网线宕机,钱也不会丢。”

6:讲讲 MySQL 的四种隔离级别,分别解决了什么问题?

[满分回答]:

“可以把隔离级别看作是数据库配的‘滤网’:

  1. RU (读未提交):没滤网。别人正在写、还没提交的半成品数据你能看见。他一回滚,你就遇到脏读
  2. RC (读已提交)动态滤网。别人没提交你看不见,解决了脏读。但因为滤网是每次查询动态生成的,别人中途提交了,你下一秒查数据就变了,这叫不可重复读
  3. RR (可重复读 - MySQL 默认)静态滤网。开启事务瞬间世界静止,别人怎么改你看到的都是初见的样子,解决了不可重复读。并且 InnoDB 极其强悍,用间隙锁(Gap Lock)锁住了查询范围的空位,把别人偷偷插数据的幻读问题也一并解决了大半。
  4. Serializable (串行化):退化成悲观锁单行道。读写互相排队,解决一切并发异常,但也把系统性能干瘫痪了。”

7:undo log 和 redo log 的区别是什么?

[满分回答]:

“它们是保证 ACID 的底层核心,区别在于:

  • redo log(重做日志):记录的是数据页的物理变化。它是为了应对服务突然宕机后的数据恢复,保证了事务的 持久性 (D)
  • undo log(回滚日志):记录的是逻辑日志(比如你 Insert,它就记 Delete)。它是为了事务失败时能回滚恢复原始数据,以及支持 MVCC 多版本控制,保证了事务的 原子性 (A)一致性 (C)。”

第三板块:高并发架构演进(项目亮点必考)

8:说说 MySQL 主从同步的原理是什么?

[满分回答]:

“主从同步核心靠的是二进制日志(Binlog),分为三步接力:

  1. 主库在事务提交时,将数据变更记录到自己的 Binlog 中。
  2. 从库通过 I/O 线程,拉取主库的 Binlog,并将其原封不动地写入自己的中继日志(Relay Log)
  3. 从库的 SQL 线程读取中继日志中的事件,在本地重做一遍,从而保证数据同步。”

9:你们的项目为什么要做分库分表?具体是怎么落地的?(整合了你的真实项目经历)

[满分回答]:

“随着我们业务的演进,垂直和水平拆分我们都用到了。

  • 垂直拆分:配合微服务,我们把业务解耦,比如把订单库和用户库物理分离开来。
  • 水平拆分(解决痛点):后来『订单库』单表突破了一千万,成为严重瓶颈。我们在 SkyRoute 短链项目中引入了 ShardingSphere 做了单库内的水平分表。
  • 路由策略:我们将短链表按 short_code、日志表按 tenant_id(租户)进行 Hash 取模,路由到了 4 张物理表中。
  • 最终效果:对业务代码完全无感知。C 端短链跳转查询能通过 short_code 精确击中单表,速度极快;如果是后台那种没带分片键的报表查询,ShardingSphere 会自动广播到 4 张表查询后再在内存里合并结果。彻底解决了海量数据下的单表读写性能瓶颈。”
✨职务:华夏大地区域代理人 | 熬夜秃头项目主理人 💳黑卡:校园一卡通全球辅导版持有者 📍地点:宇宙-银河系-地球-东北蹲分部 🥂生活方式:沉迷于廉价多巴胺 | 致力于在该醒的时候睡觉 🚫拒绝:拒绝早起 | 拒绝内卷| 拒绝借钱 简介:虽然我没钱,但我有时间;虽然我没才华,但我有脾气。
最后更新于 2026-06-03