阿里云数据库内核开发面试经历:存储引擎+事务实现深度考察
3年数据库内核开发经验,完整复盘阿里云PolarDB三轮技术面试,涵盖C++、B+树、MVCC、WAL、存储引擎设计等核心考点,附真题汇总与备考建议。
背景介绍
我做了3年数据库内核开发,之前在一家数据库创业公司做存储引擎相关的工作,主要用C++写存储层和事务层的代码。对B+树、LSM-Tree这些数据结构算是比较熟悉了。阿里云PolarDB的数据库内核开发岗位是我一直想去的,毕竟PolarDB是国产云数据库的标杆,技术深度和工程规模都是顶级的。
我是通过前同事内推的,岗位是PolarDB数据库内核开发工程师。内推后大概一周收到了面试邀请。整个流程是三轮技术面,没有单独的HR面,周期大概三周。
面试流程复盘
一面:C+++数据结构(约60分钟)
一面面试官是组里的高级开发,开场先聊了下我的项目经历,然后直接进入技术环节。
C++部分:面试官问了智能指针的实现原理,shared_ptr的引用计数怎么保证线程安全,我说了用原子操作。然后问了RAII机制、move语义、完美转发。还问了一个比较细节的问题:unique_ptr为什么不能拷贝,我说了删除了拷贝构造函数和拷贝赋值运算符。面试官又追问了如果要在函数间传递unique_ptr怎么办,我说用std::move。
数据结构部分:面试官让我手写一个LRU Cache,要求O(1)的get和put。我用了哈希表+双向链表的经典方案,写完面试官让我分析时间复杂度和空间复杂度。然后问了红黑树和B+树的区别,以及在数据库索引中为什么选择B+树而不是红黑树。我从磁盘IO的角度详细解释了B+树的优势:更大的扇出、更少的层级、范围查询友好。
算法部分:给了一道题——在一个有序数组中找到第一个大于等于target的元素,就是lower_bound的实现。我写了二分查找,面试官让我证明正确性,我用了循环不变量来证明。
一面整体感觉偏基础,但问得比较细,不是那种浮于表面的八股。
二面:B+树+MVCC+WAL(约90分钟)
二面是整个面试最硬核的一轮,面试官是数据库内核的资深专家。
B+树部分:面试官让我详细讲B+树的插入和删除过程,包括节点的分裂和合并。我画了分裂的示意图,讲了中间key上提的逻辑。面试官追问了B+树在并发场景下怎么做,我讲了 latch coupling(蟹行协议)的方案,以及B-link Tree的优化思路。然后问了一个很深入的问题:B+树节点分裂时如果crash了怎么办?我说了通过WAL日志保证原子性,分裂操作先写日志再修改页面。
MVCC部分:面试官让我详细讲InnoDB的MVCC实现,包括隐藏列(DB_TRX_ID、DB_ROLL_PTR)、Undo Log的版本链、Read View的可见性判断规则。我按照RC和RR两个隔离级别分别讲了Read View的生成时机不同。面试官追问了RR级别下为什么不能完全避免幻读,我讲了当前读和快照读的区别,以及Next-Key Lock如何解决幻读。然后问了一个开放题:如果让你设计一个MVCC方案,你会怎么做?我从版本存储、垃圾回收、可见性判断三个维度回答了。
WAL部分:面试官问了WAL的原理和作用,Redo Log的写入流程(先写Log Buffer再刷盘),以及组提交(Group Commit)的优化。然后问了一个关键问题:如何保证Redo Log和Binlog的一致性?我讲了两阶段提交的方案,XA协议的流程,以及如果某阶段crash了怎么恢复。面试官对这个回答比较满意,又追问了分布式事务的2PC和数据库内部2PC的区别。
二面聊了整整90分钟,感觉脑力消耗巨大,但也确实过瘾。
三面:存储引擎设计+项目深挖(约75分钟)
三面面试官应该是技术总监级别的,问题更偏向架构和设计。
存储引擎设计:面试官给了一个开放题——如果让你设计一个支持高并发写入的存储引擎,你会怎么设计?我从LSM-Tree的架构讲起,说了MemTable、Immutable MemTable、SSTable的分层结构,以及Compaction策略。面试官追问了LSM-Tree的读放大问题怎么解决,我讲了Bloom Filter、索引分层、缓存策略。然后面试官让我比较LSM-Tree和B+ Tree的优劣,以及什么场景下该选哪个。我从写放大、读放大、空间放大三个维度做了对比分析。
项目深挖:面试官让我详细讲了之前做的一个页面压缩功能,从需求背景、方案设计到性能测试。我重点说了字典压缩和变长页的方案,面试官对压缩率的提升很感兴趣,问了具体的测试数据。然后问了我遇到过最难的技术问题是什么,我讲了一个并发Bug的排查过程,从现象到定位到修复,面试官听得很认真。
综合考察:面试官问了我对云原生数据库的理解,存储计算分离的架构优势,以及PolarDB和Aurora的架构差异。我从日志即数据的理念、共享存储的实现、RO节点的扩展性几个角度分析了。
真题汇总
1. shared_ptr的引用计数怎么保证线程安全?
2. unique_ptr为什么不能拷贝?如何在函数间传递?
3. 手写LRU Cache,要求O(1)的get和put
4. 为什么数据库索引选择B+树而不是红黑树?
5. B+树节点的分裂和合并过程?
6. B+树在并发场景下怎么做?latch coupling方案?
7. B+树节点分裂时crash了怎么办?
8. InnoDB的MVCC实现原理?
9. RR级别下为什么不能完全避免幻读?
10. 如何设计一个MVCC方案?
11. WAL的原理和作用?Redo Log的写入流程?
12. 如何保证Redo Log和Binlog的一致性?
13. 设计一个支持高并发写入的存储引擎
14. LSM-Tree的读放大问题怎么解决?
15. LSM-Tree和B+ Tree的优劣对比?
16. PolarDB和Aurora的架构差异?
心得建议
1. C++基础要扎实到细节:数据库内核开发对C++的要求非常高,不是会写就行,还要理解底层机制。智能指针、RAII、move语义这些几乎是必考的,建议仔细读《Effective C++》和《C++ Concurrency in Action》。
2. 数据结构要能手写能讲清:B+树是数据库内核面试的核心考点,不仅要能讲清楚原理,还要能手写关键操作。建议自己实现一个简化版的B+树。
3. 事务和并发控制是重中之重:MVCC、WAL、2PC这些是数据库内核的灵魂,面试中几乎一定会深挖。建议读《Database System Concepts》的事务章节和《MySQL技术内幕:InnoDB存储引擎》。
4. 要有系统设计的全局观:三面的存储引擎设计不是考你某个组件,而是考你对整个存储引擎架构的理解。建议读LevelDB和RocksDB的源码,理解LSM-Tree的完整实现。
5. 项目经验要有深度:面试官会深挖你的项目细节,包括设计决策的原因、遇到的问题和解决方案。建议准备2-3个有深度的项目,用STAR法则梳理。
FAQ
Q:阿里云数据库内核面试对C++要求到什么程度?
A:要求比较高。不是那种"会写C++就行"的程度,而是要理解C++的内存模型、并发机制、模板元编程等。建议至少有3万行以上的C++项目经验。
Q:没有数据库内核经验能过吗?
A:很难。阿里云PolarDB岗位明确要求有数据库内核开发经验。如果只有应用层经验,建议先参与一些开源数据库项目,比如TiDB、RocksDB。
Q:面试会问操作系统和计算机体系结构吗?
A:会。数据库内核和OS紧密相关,面试官会问内存管理、文件系统、CPU缓存等相关知识。建议复习操作系统课程的重点章节。
Q:PolarDB团队的工作强度大吗?
A:据我了解,PolarDB团队的工作强度在阿里云内部算中等偏上,但技术氛围很好,能学到很多东西。面试官也提到团队有比较完善的技术分享机制。