【面试题】1. 数据库核心原理:一条 SELECT 语句在 MySQL 里是怎么执行的?说完整链路。
【标准答案】客户端发 SQL 过来,先经过连接器做权限验证,然后查查询缓存(8.0 已废弃),没命中就到分析器做词法语法解析生成 AST,接着优化器根据统计信息选索引、定 join 顺序、生成执行计划,最后执行器调用存储引擎接口逐行读取、过滤、排序、返回。关键是优化器这一步,它不一定选最优方案,索引统计信息不准或者 SQL 写法不好都可能导致选错。
【面试题】2. 说说 ACID 里的 I(隔离性),四个隔离级别各解决了什么问题?
【标准答案】隔离性解决并发事务互相干扰的问题。读未提交最低,完全不隔离,有脏读。读已提交每次读到最新已提交数据,解决脏读但会有不可重复读。可重复读是 InnoDB 默认级别,用 MVCC 保证事务内读同一行看到的值不变,解决不可重复读但可能有幻读(InnoDB 用间隙锁也解决了)。串行化最强,事务排队执行,性能最差。面试要记住:InnoDB 的 RR 级别通过 MVCC + 间隙锁基本解决了幻读,别死记理论。
【面试题】3. InnoDB 和 MyISAM 的核心区别,为什么现在默认用 InnoDB?
【标准答案】四个核心区别:一、InnoDB 支持事务和崩溃恢复,MyISAM 不支持,断电丢数据;二、InnoDB 行级锁,MyISAM 表级锁,并发差一个量级;三、InnoDB 用聚簇索引,数据和主键绑一起,MyISAM 数据和索引分离;四、InnoDB 有 Buffer Pool 缓存数据和索引,MyISAM 只缓存索引。MySQL 5.5 开始切到 InnoDB 是必然的,OLTP 场景下事务和行锁是刚需,MyISAM 现在只剩只读日志表这种极窄场景还有人在用。
【面试题】4. B+Tree 索引原理:为什么 MySQL 不选 B-Tree 也不选 Hash,偏偏用 B+Tree?
【标准答案】三个原因:一、B+Tree 所有数据都在叶子节点,非叶子只存索引键,同样高度能存更多数据,磁盘 IO 更少;二、叶子节点之间有双向链表串联,范围查询比如 WHERE id BETWEEN 100 AND 200 直接顺着链表扫就行,B-Tree 得反复回溯,Hash 索引根本做不了范围查询;三、查询效率稳定,任何数据都要走到叶子层,B-Tree 可能在非叶子就命中了但波动大。B+Tree 就是为磁盘 IO 和范围查询而生的。
【面试题】5. 给你一个慢查询,从排查到优化你的完整思路是什么?
【标准答案】第一步打开 slow_query_log,或者直接看 performance_schema 里 1 秒以上的 SQL。第二步拿到 SQL 用 EXPLAIN 看执行计划,重点关注 type 列(ALL 全表扫描直接报警)、rows(扫描行数过大)、Extra(Using filesort 和 Using temporary 要排查)。第三步看索引:where 条件列、join 列、order by 列有没有索引,联合索引最左前缀有没有用到。第四步优化手段:该加索引加索引,该改写 SQL 就改写(避免函数包裹索引列、避免 select *、大偏移量用延迟关联)。最后压测验证。
【面试题】6. MySQL 行锁、间隙锁、Next-Key Lock 分别是什么?什么场景会产生死锁?
【标准答案】行锁锁住具体一行,并发高时最友好。间隙锁锁住索引记录之间的空隙,防止幻读。Next-Key Lock 是行锁 + 前面间隙锁的组合,InnoDB 的 RR 级别加锁就是这个。死锁经典场景:事务 A 先锁 id=1 再要锁 id=2,事务 B 先锁 id=2 再要锁 id=1,互相等待,GG。排查用 SHOW ENGINE INNODB STATUS 看 LATEST DETECTED DEADLOCK 部分,解决方式要么调小事务粒度,要么保证访问顺序一致,要么加超时重试。
【面试题】7. Redis 的 RDB 和 AOF 持久化怎么选?各自缺点是什么?
【标准答案】RDB 是快照,定期把全量内存数据写磁盘,恢复快、文件小,但两次快照之间的数据可能丢。AOF 是追加写命令日志,默认每秒刷盘,数据安全性高但文件大恢复慢。生产环境通常两个都开:RDB 做冷备全量恢复,AOF 保证数据不丢。注意 AOF 文件会膨胀,要配 rewrite 策略自动压缩。Redis 4.0 以后有混合持久化,RDB 格式写快照 + AOF 写增量,兼顾恢复速度和数据安全,推荐用这个。
【面试题】8. 分库分表方案怎么落地?ShardingSphere 和 MyCat 怎么选?
【标准答案】先确定分片键,一般选查询最频繁的字段比如 user_id 或 order_id,要保证 80% 的查询能带上分片键避免全库扫。分片策略常用一致性哈希或取模。ShardingSphere 是中间件框架,JDBC 模式无代理层性能损耗小但语言绑定 Java,Proxy 模式解耦但多一跳;MyCat 是老牌独立代理,SQL 兼容性好但社区活跃度下降。中小团队选 ShardingSphere-JDBC 够用,大团队异构语言多才上 Proxy。有一点必须记住:分库分表后跨库 join、分布式事务、全局 ID 都得重新设计,不是加个中间件就完事了。
【面试题】9. 分布式事务怎么搞?CAP 理论在工程上的取舍是什么?
【标准答案】CAP 说一致性、可用性、分区容错只能同时满足两个,但网络分区在生产环境不可避免,所以 P 必须选,剩下在 C 和 A 之间权衡。银行转账场景强一致用 2PC 或 TCC,但性能差;电商下单用最终一致,比如本地消息表 + 定时任务补发,或者 RocketMQ 事务消息。Seata 的 AT 模式本质是 2PC 的改良版,自动回滚 undo log。核心经验:能避免分布式事务就避免,用本地事务 + 异步补偿兜底比硬上 2PC 靠谱得多。
【面试题】10. Flink 相比 Spark Streaming 做实时计算的核心优势是什么?
【标准答案】先说最核心的:Flink 是真正的逐条流处理,Spark Streaming 是微批次(micro-batch),延迟上 Flink 可以到毫秒级,Spark Streaming 最短也得秒级。其次 Flink 的状态管理更成熟,有 RocksDB 做后端支持超大状态,exactly-once 语义通过 checkpoint + 两阶段提交实现。窗口计算上 Flink 支持事件时间 + watermark 处理乱序数据,Spark Streaming 对乱序的处理弱很多。选型原则:秒级延迟够用的离线 + 实时一体场景用 Spark,毫秒级纯实时用 Flink,别无脑梭哈。