{ "topic": "database-advanced", "type": "fill_blank", "schema_version": "1.0.0", "generated": "2026-09-09T00:00:00+08:00", "questions": [ { "id": "fb-001", "type": "fill_blank", "difficulty": 2, "tags": [ "mysql", "bplus-tree", "index" ], "question": "在 InnoDB 中,主键索引的叶子节点直接存储______,因此基于主键查询效率最高;而二级索引的叶子节点存储的是主键值,查到后通常还需要______才能获取完整行数据。", "answer": [ "完整行数据", "整行数据", "完整的行数据", "聚簇索引回表", "回表" ], "answer_rule": "any", "explanation": "InnoDB 使用聚簇索引(Clustered Index),主键索引的 B+ 树叶子节点存储的是完整的行数据,因此通过主键查询可以直接获取数据,无需额外的 IO。而二级索引(非聚簇索引)的叶子节点只存储主键值,查到主键后需要拿着主键回到聚簇索引中查找完整行数据,这个过程称为「回表」。回表会产生额外的随机 IO,是影响查询性能的重要因素。", "source": null, "related": [] }, { "id": "fb-002", "type": "fill_blank", "difficulty": 3, "tags": [ "mysql", "index", "composite-index" ], "question": "联合索引 (a, b, c) 遵循最左前缀原则,以下查询中能使用该索引的有:WHERE a=1 AND b=2、WHERE a=1 AND c=3、WHERE b=2 AND c=3、WHERE a=1 ORDER BY b。其中 ______ 的查询无法使用索引(填查询条件序号,如 2、3)。", "answer": [ "2、3", "2和3", "b=2 AND c=3, a=1 AND c=3", "第2个和第3个", "WHERE a=1 AND c=3, WHERE b=2 AND c=3" ], "answer_rule": "any", "explanation": "最左前缀原则要求查询条件从联合索引的最左列开始连续匹配。索引 (a, b, c):① WHERE a=1 AND b=2 命中前两列,可使用索引;② WHERE a=1 AND c=3 跳过了 b,只能用到 a 这一列,c 无法使用索引过滤;③ WHERE b=2 AND c=3 完全跳过了最左列 a,无法使用索引;④ WHERE a=1 ORDER BY b 命中 a 列,排序字段 b 在索引中紧跟 a,可避免 filesort。因此第 2、3 个查询无法有效利用索引。", "source": null, "related": [] }, { "id": "fb-003", "type": "fill_blank", "difficulty": 3, "tags": [ "mysql", "index", "covering-index" ], "question": "当查询所需的所有列都包含在索引中时,MySQL 可以直接从索引获取数据而无需回表,这种技术称为______。在 EXPLAIN 的 Extra 列中会显示为 ______。", "answer": [ "覆盖索引", "Using index" ], "answer_rule": "all", "explanation": "覆盖索引(Covering Index)是指查询需要的所有字段都被某个索引所覆盖,InnoDB 只需扫描索引即可完成查询,避免了回表操作。此时 EXPLAIN 的 Extra 列会显示「Using index」,表示使用了覆盖索引。覆盖索引是优化查询性能的重要手段,能显著减少随机 IO。例如对索引 (name, age) 执行 SELECT name, age FROM users WHERE name = 'Tom',所有需要的列都在索引中,无需回表。", "source": null, "related": [] }, { "id": "fb-004", "type": "fill_blank", "difficulty": 4, "tags": [ "mysql", "index", "bplus-tree" ], "question": "MySQL 5.6 引入的索引下推(Index Condition Pushdown,ICP)优化,将 ______ 下推到存储引擎层在索引扫描阶段完成过滤。在 EXPLAIN 的 Extra 列中,启用 ICP 时会显示 ______。", "answer": [ "WHERE 条件过滤", "部分 WHERE 条件", "索引不覆盖的过滤条件", "Using index condition" ], "answer_rule": "all", "explanation": "索引下推(ICP)是 MySQL 5.6 引入的优化。在没有 ICP 之前,存储引擎根据索引找到记录后回表,Server 层再进行 WHERE 过滤。ICP 将部分 WHERE 条件下推到存储引擎层,在索引扫描时就进行过滤,减少了回表次数和 Server 层的处理开销。当 ICP 生效时,EXPLAIN Extra 列显示「Using index condition」。注意 ICP 仅适用于 InnoDB 和 MyISAM,且只对联合索引起作用——因为单列索引的叶子节点已经包含了完整信息,不需要额外过滤。", "source": null, "related": [] }, { "id": "fb-005", "type": "fill_blank", "difficulty": 2, "tags": [ "mysql", "explain" ], "question": "EXPLAIN 执行计划的 type 列中,性能从好到差的大致顺序为:system > ______ > eq_ref > ref > range > index > ALL。其中 ______ 表示全表扫描,通常需要重点优化。", "answer": [ "const", "ALL" ], "answer_rule": "all", "explanation": "EXPLAIN 的 type 列表示 MySQL 在表中找到匹配行的方式。const 表示通过主键或唯一索引查找到单行(如 WHERE id=1),速度最快;eq_ref 表示对每一行的 JOIN 都从表中用主键/唯一索引查一行;ref 表示使用普通索引查找;range 表示索引范围扫描;index 表示全索引扫描;ALL 是全表扫描,性能最差。type 列是从左到右性能递减的,日常优化目标至少是 range 级别,避免 ALL。", "source": null, "related": [] }, { "id": "fb-006", "type": "fill_blank", "difficulty": 3, "tags": [ "mysql", "slow-query", "explain" ], "question": "慢查询日志通过设置 ______ 参数(单位秒)开启,超过该阈值的查询会被记录。在 EXPLAIN 的 Extra 列中,______ 表示 MySQL 需要额外的排序操作,______ 表示使用了临时表,二者都可能消耗较多内存和 CPU,需要重点关注优化。", "answer": [ "slow_query_log", "long_query_time", "Using filesort", "Using temporary" ], "answer_rule": "any", "explanation": "慢查询日志通过 slow_query_log=ON 开启,long_query_time 设置阈值(默认 10 秒)。建议生产环境设为 1 秒甚至更低。EXPLAIN Extra 中:「Using filesort」表示 MySQL 无法利用索引完成排序,需要额外的排序算法(通常因为 ORDER BY 字段不在索引中);「Using temporary」表示使用了临时表(常见于 GROUP BY、DISTINCT、子查询等场景)。这两者通常意味着较大的内存和 CPU 开销,尤其在数据量大时性能影响显著,应通过优化索引和 SQL 来避免。", "source": null, "related": [] }, { "id": "fb-007", "type": "fill_blank", "difficulty": 4, "tags": [ "mysql", "lock" ], "question": "InnoDB 中,行锁基于索引实现,锁住的是索引记录而非物理行。当查询未命中索引时,InnoDB 会退化为______锁,锁定所有行,严重影响并发。间隙锁(Gap Lock)锁定的是索引记录之间的间隙,用于防止______插入,从而解决幻读问题。", "answer": [ "表锁", "幻读", "新行", "其他事务的" ], "answer_rule": "any", "explanation": "InnoDB 的行锁是通过给索引上的索引项加锁来实现的。如果 WHERE 条件没有走索引(如全表扫描),InnoDB 将锁住整个表(所有行),等效于表锁,严重降低并发性能。间隙锁(Gap Lock)锁住的是索引记录之间的「间隙」,以及第一条记录之前和最后一条记录之后的间隙,其目的是防止其他事务在间隙中插入新记录,从而避免幻读(Phantom Read)。临键锁(Next-Key Lock)= 行锁 + 间隙锁,是 InnoDB 在可重复读隔离级别下的默认锁类型。", "source": null, "related": [] }, { "id": "fb-008", "type": "fill_blank", "difficulty": 4, "tags": [ "redis", "cluster", "slot" ], "question": "Redis Cluster 使用一致性哈希将数据分布在 16384 个 slot 中,每个 key 通过 CRC16 算法对 16384 取模确定所属 slot。当需要迁移 slot 时,使用 ______ 命令将 key-value 从源节点转移到目标节点,迁移过程中需要同时保持源和目标节点对该 slot 的访问。", "answer": [ "MIGRATE", "migrate" ], "answer_rule": "any", "explanation": "Redis Cluster 采用 16384 个虚拟节点(slot)来分配数据。每个 key 通过 CRC16(key) % 16384 确定 slot 编号,每个 master 节点负责一部分 slot。MIGRATE 命令用于在节点间迁移 key,它是一个原子操作:先在目标节点还原 key,成功后在源节点删除。迁移过程中,Redis Cluster 会通过 ASK/MOVED 重定向来保证客户端能正确路由请求。Redis Cluster 没有使用虚拟节点的概念,而是用固定的 16384 个 slot 做直接映射,每个节点负责一段连续的 slot 范围。", "source": null, "related": [] }, { "id": "fb-009", "type": "fill_blank", "difficulty": 3, "tags": [ "redis", "sentinel" ], "question": "Redis 哨兵(Sentinel)模式至少需要部署 ______ 个哨兵节点,以避免脑裂问题。哨兵通过类似 Raft 的协议选举 leader,当多数哨兵确认 master 不可达时触发故障转移。Sentinel 还负责 ______,即将新的 master 地址通知给所有客户端。", "answer": [ "3", "客户端通知", "通知客户端", "配置发布", "发布新的 master 地址" ], "answer_rule": "any", "explanation": "Redis Sentinel 至少需要 3 个节点才能保证高可用,因为故障判定需要 quorum(多数派)同意。如果只有 2 个哨兵,任何一个挂掉都无法达成多数派,失去了容错能力。Sentinel 使用类似 Raft 的算法进行 leader 选举:当检测到 master 下线时,哨兵之间互相通信,通过投票选出 leader 来执行故障转移。故障转移完成后,Sentinel 通过「配置发布/订阅」机制(Pub/Sub)通知所有连接的客户端新的 master 地址,客户端会自动重连。", "source": null, "related": [] }, { "id": "fb-010", "type": "fill_blank", "difficulty": 4, "tags": [ "redis", "hybrid-persistence", "active-defrag", "lru" ], "question": "Redis 4.0 引入的混合持久化机制在 AOF rewrite 时,先以 RDB 格式写入当前全量数据,再追加 rewrite 期间的增量 AOF 命令,兼顾了 ______ 和 ______ 的优势。Redis 4.0 还引入了 ______ 功能,通过后台线程扫描并整理内存碎片,减少因频繁删改导致的内存浪费。当内存达到 maxmemory 时,Redis 根据 ______ 策略淘汰 key,常用策略包括 allkeys-lru、volatile-lru、volatile-lfu 等。", "answer": [ "RDB 恢复速度", "AOF 数据完整性", "恢复速度", "数据安全", "active-defrag", "active-defragging", "内存淘汰" ], "answer_rule": "any", "explanation": "混合持久化(Hybrid Persistence)结合了 RDB 和 AOF 的优点:AOF rewrite 时先写 RDB 快照(恢复速度快),再追加增量 AOF 命令(保证数据完整性),大幅缩短了重启恢复时间。active-defrag 是 Redis 4.0 引入的主动内存碎片整理功能,通过后台线程对内存进行碎片扫描和重新分配,无需重启即可释放碎片内存,可通过 activedefrag yes 开启。Redis 的内存淘汰策略在内存达到 maxmemory 时触发:allkeys-lru 对所有 key 做 LRU 淘汰;volatile-lru 只对设了过期时间的 key 做 LRU;volatile-lfu 使用 LFU(最不经常使用)算法淘汰。LFU 比 LRU 更精准,能淘汰真正不活跃的 key。", "source": null, "related": [] } ] }