秋招季收到小满的数据库岗笔试邀请时,我其实没有太多意外——这批岗位投递量不小,数据库方向又是后端技术栈里的硬骨头,笔试通常不会太客气。真正坐下来打开试卷,两个小时做完,心里只有一个感受:这份笔试题比大多数互联网公司的同类岗位要扎实,覆盖面很广,从基础SQL到锁机制、从数据库设计到国产数据库趋势都有涉及,而且很多题目不是背概念就能过的,需要真正理解数据库底层原理才能写出有说服力的答案。
这篇文章我打算完整复盘这次“2023年度小满秋招数据库岗第一批笔试”的题目和我的作答思路,重点不只是给答案,而是把每道题背后的知识点、我当时是怎么思考的、哪些地方容易踩坑、以及考完之后又补充补了哪些内容,都一并整理出来。如果你正在准备数据库岗的笔试,或者想系统梳理一下数据库知识体系,这篇复盘应该能帮你在复习时少走很多弯路。
1. 笔试全流程:从投递到收卷的完整记录
1.1 笔试形式与时间分配
小满这轮第一批笔试采用的是在线笔试系统,双机位监控,需要在规定时间内完成并提交,整体体感和很多大厂校招笔试类似。题目总量不算特别多,我记得大概是:单选题15道、多选题5道、判断题5道、手写SQL题3道、数据库设计题1道、简答/场景题2道,总共31道题的样子,考试时长120分钟。
时间分配上我做了个大致的规划:选择题和判断题控制在40分钟内完成,因为这部分只要基础扎实,每题基本30秒到1分钟内能搞定;手写SQL题留了40分钟,三道题的难度是递进的,从单表查询到多表关联再到窗口函数和复杂子查询,需要留足思考和调试的时间;最后数据库设计题和简答题留了40分钟,这部分需要写文字说明,比较费时间,还要注意排版逻辑清晰。
实际做下来,选择题比预期要多花了一点时间,主要是有几道多选题对隔离级别和锁机制的考法比较绕,宁可多花30秒确认也不愿意蒙。最后做完还剩大约15分钟,我把SQL题的写法重新检查了一遍,特别是字段别名、GROUP BY后面的条件过滤顺序这些细节,确实发现了一处小问题,这15分钟花得很值。
1.2 整体题型分布与考察重点
从知识板块来看,这试卷的覆盖面相当广,我考完之后做了个分类,大致如下:
| 知识板块 | 题量 | 考察深度 |
|---|---|---|
| SQL基础(增删改查、聚合、关联) | 约8题 | 中,偏手写能力 |
| 索引与执行计划 | 约5题 | 中高,涉及索引失效、覆盖索引 |
| 事务、锁与隔离级别 | 约6题 | 高,很多题目结合场景分析 |
| 数据库设计与范式 | 约3题 | 中,涉及ER图、反范式设计 |
| 存储引擎与日志机制 | 约4题 | 高,重点在InnoDB、redo/undo/binlog |
| 备份恢复与主从复制 | 约3题 | 中高,考察同步方式和数据一致性 |
| 国产数据库与新技术趋势 | 约2题 | 中,只需了解生态和核心差异 |
这个分布其实很有代表性。它没有刻意去考某些偏门数据库的冷门函数,而是把重点放在所有数据库岗都必须掌握的核心能力上:SQL功底、事务与并发控制、索引优化、数据一致性方案。同时它又通过两道拓展题考查你对行业趋势的关注度,这一点在后面的章节我会详细展开。
2. 基础题复盘:选择题里藏着的硬功夫
2.1 SQL语法与增删改查易错点
选择题第一梯队考的自然是SQL基础,但出题人不会老老实实问你“SELECT是干嘛的”这种送分题,而是会设置各种容易混淆的陷阱。我记得有一道题是这样的:
题目大意:一张学生表 student(id, name, score),需要查出成绩大于80分的学生中,每个分数段(按10分为一段)对应的人数,并按人数降序排列。给出四个SQL选项,选正确的。
这个题考察的本质是GROUP BY + 条件过滤的顺序问题。很多人容易犯错的地方在于:WHERE和HAVING到底谁先执行、能不能混用。这里明确说一下,WHERE是在分组前对原始记录进行过滤,HAVING是在分组之后对聚合结果进行过滤,所以“成绩大于80分”这个条件必须放在WHERE子句中,因为它是对明细数据的过滤。如果误放在HAVING后面,虽然部分数据库也能跑,但逻辑上不是最优的,而且通过不了对性能要求严苛的场景。
我当时看到这道题几乎没犹豫,因为类似的坑在平时刷题时踩过太多次了。这也提醒大家:数据库岗笔试的选择题,很少考孤立的知识点,大多数是“一个考点搭一个易混点”的组合。复习的时候不能只记语法,要把每种子句的执行顺序背清楚——FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT,这个顺序是SQL优化的根基。
还有一个印象比较深的题目是关于DELETE和TRUNCATE的区别。选项里有“DELETE可以加WHERE条件,TRUNCATE不可以”、“TRUNCATE会触发触发器”、“DELETE删除后可以回滚,TRUNCATE不一定可以”、“TRUNCATE比DELETE快”。这四个选项分别对应4个小知识点,属于典型的“一题多考”模式。正确答案是DELETE可以加WHERE、TRUNCATE更快、DELETE在事务内可回滚而TRUNCATE在某些数据库中的回滚行为不同。至于触发器,TRUNCATE在MySQL里不会逐行触发DELETE触发器,这个点比较冷门,但确实是大厂笔试爱考的。
2.2 索引机制与执行计划
索引相关的题在笔试中占比不低,而且往往结合EXPLAIN执行计划来考。有一道多选题让我印象很深,题目列出几种SQL写法,问哪些情况下索引会失效。我把自己选的项和对应的判断依据梳理一下:
- 对索引列使用函数,比如 WHERE YEAR(create_time) = 2023,索引失效。
- 隐式类型转换,比如索引列是varchar,但查询条件用的是数字,索引失效。
- LIKE以通配符开头,比如 WHERE name LIKE '%张',索引失效。
- 使用OR连接非索引列,比如 WHERE id = 1 OR name = '张三',如果name没有索引,整个查询可能放弃走索引。
这个知识点本身不复杂,但笔试往往会在选项里增加干扰项,比如“WHERE name LIKE '张%'是否会走索引”、“WHERE id IN (1,2,3) 是否能走索引”这些变体。我当时特别注意了IN和EXISTS的区别,以及覆盖索引(Covering Index)的优化效果。所谓覆盖索引,就是查询的列全部包含在索引中,这样可以直接从索引返回结果,不需要回表。笔试题如果问“如何优化一条查询”,优先考虑覆盖索引往往是比较稳的回答方向。
还有一个关于联合索引最左前缀原则的题目,考的是复合索引 (a, b, c) 在哪些查询条件下可以命中。这种情况要记得:可以跳过中间的b直接查a和c吗?答案是不行。最左前缀原则要求查询条件必须包含索引的最左列,而且中间列不能断。比如WHERE a=1 AND c=3,只能用到a列索引;WHERE b=2 AND c=3,则完全用不到这个联合索引。这部分我建议复习时画一张表,把可能的条件组合列全,多推演几遍就熟了。
2.3 事务隔离级别与MVCC
事务这块是这个笔试的“重头戏”,多选题和简答题都有覆盖。有一个题目给了四种隔离级别,问哪种隔离级别下不会出现脏读但可能出现不可重复读。这个答案显然是READ COMMITTED,因为READ COMMITTED解决了脏读问题,但允许在同一事务中执行相同查询返回不同结果,也就是不可重复读。
但笔试不只是让你选级别而已,真正难的是让你判断某个具体场景下会发生什么。我记得有一道类似这样的场景题:
事务A先查询某条记录的balance为100,然后事务B修改balance为200并提交,接着事务A再次查询balance。问在READ COMMITTED和REPEATABLE READ下,第二次查询结果分别是什么?
在READ COMMITTED下,事务A第二次查询会看到200,因为每次SELECT都会读取已提交的最新数据;而在REPEATABLE READ下,事务A第二次查询仍然看到100,因为MySQL InnoDB通过MVCC保证了事务内的快照一致性。这个知识点背后的原理就是MVCC(多版本并发控制),具体实现依赖undo log中的版本链和ReadView机制。
笔试之后我复盘时把MVCC的规则重新梳理了一遍:读操作在REPEATABLE READ下会创建一个ReadView,之后的查询都基于这个ReadView来判断行的可见性;而读已提交级别下每次SELECT都会重新生成ReadView,因此能看到新提交的数据。如果只是应付选择题,记住“RR下事务内快照一致、RC下每次读最新已提交”就够了,但如果面试时要深挖,建议大家打开源码级别去理解,尤其是活跃事务列表、已提交事务数组这些概念。
另外今年笔试还考了一道死锁相关的选择题,问死锁产生的四个必要条件是什么。这个题没什么花样,就是互斥、持有并等待、不可剥夺、循环等待。但后面跟了一个判断题比较有意思:InnoDB检测到死锁后,会回滚其中一个事务来解除死锁,这个说法对不对?答案是“不完整”,InnoDB确实会回滚其中一个事务,但它是通过检测循环等待,然后选择回滚undo log量较小的事务,并不是随机回滚。这类题目单纯背概念远远不够,必须对InnoDB的死锁检测机制有一定了解。
2.4 InnoDB存储引擎与日志机制
存储引擎和日志这部分的题比较硬核,选择题里涉及了InnoDB和MyISAM的区别、redo log和binlog的区别。我记得有一道题专门问redo log的刷盘策略,选项里包含了innodb_flush_log_at_trx_commit取值为0、1、2时的行为。
这个知识点是数据库岗笔试的高频题,必须弄明白:取值为0时,事务提交不写入redo log,而是每秒刷一次缓存到磁盘,性能最高但可能丢失最后一秒的数据;取值为1时,每次事务提交都会把redo log刷到磁盘,保证不丢数据,性能开销最大;取值为2时,事务提交时把redo log写入操作系统缓存,再每秒刷盘,MySQL宕机不丢但操作系统宕机可能丢。我在笔试时把三个值对性能和一致性的影响写清楚了,这种题一般不要求你背出官方文档原文,而是考察你是否理解“刷盘时机”决定了“崩溃恢复窗口”。
关于redo log与binlog的区别,题目考察得也挺细:redo log是InnoDB层产生的物理日志,记录的是“对数据页做了哪些修改”,用于崩溃恢复;binlog是MySQL Server层产生的逻辑日志,记录的是“执行的SQL或行变更”,用于主从复制和时间点恢复。两者还有一点容易混淆,redo log是循环写的,binlog是追加写的。如果遇到问“为什么主从复制用的是binlog而不是redo log”的题,可以从逻辑复制与物理复制的区别、跨版本兼容性、可审计性等角度作答。
日志机制部分还顺带问到了undo log的作用,这个比较好答:事务回滚时,通过undo log把数据恢复到修改前的状态;同时undo log还是MVCC实现多版本可见性的基础。到这里选择题基本收官,这套题的选择部分最大的体会是:它不是考你“知不知道”,而是考你“懂不懂”,很多选项都对但场景不同结论就不同,必须结合具体语境判断。
3. SQL实战与场景设计题:真正的分水岭
3.1 手写SQL题:从单表查询到复杂关联
笔试的手写SQL题是拉开差距的关键。三道题由易到难,第一道是经典的“查第二高工资”。题目是给一个员工表 employee(id, name, salary),查出工资第二高的员工姓名和工资,不存在则返回NULL。
这种题有很多写法,我当时写的是先用子查询查出最高工资,再用WHERE排除最高工资后取MAX,一层套一层:
SELECT name, salary FROM employee WHERE salary = ( SELECT MAX(salary) FROM employee WHERE salary < (SELECT MAX(salary) FROM employee) );这种写法好处是逻辑直白,不容易漏,缺点是不够优雅。很多人可能会用LIMIT 1 OFFSET 1,但如果表里存在并列最高工资,这种写法可能把第二高也过滤掉,而且“不存在则返回NULL”这个需求处理起来比较别扭。笔试时我特意在答案里备注了一句,说明如果数据库支持窗口函数,更推荐用 DENSE_RANK() 实现,因为它能正确处理并列排名的情况。
第二道SQL题考了一个多表关联的统计场景,大概是订单表 orders(order_id, user_id, amount, create_time) 和用户表 users(user_id, name, register_time),要求统计2023年每个月的新注册用户在当月产生的订单总金额。这个题核心是两件事:一是日期格式化,二是等值关联加聚合。我的写法是:
SELECT DATE_FORMAT(u.register_time, '%Y-%m') AS reg_month, SUM(o.amount) AS total_amount FROM users u LEFT JOIN orders o ON u.user_id = o.user_id AND o.create_time >= u.register_time AND o.create_time < DATE_ADD(u.register_time, INTERVAL 1 MONTH) WHERE u.register_time BETWEEN '2023-01-01' AND '2023-12-31' GROUP BY DATE_FORMAT(u.register_time, '%Y-%m') ORDER BY reg_month;这里有个细节值得注意:JOIN条件里我为什么要加 o.create_time >= u.register_time?因为如果只是简单关联,会把用户注册之前下的订单也算进去,这就不符合“新注册用户在当月产生的订单”这个语义了。笔试时最容易出错的地方就是JOIN条件与WHERE条件的边界——JOIN ON里写的是关联时对右表的过滤条件,而WHERE里是对左表的过滤条件,两者混用会导致结果集差异。写完后我把这种题目归类为“时序相关统计”,它考察的不只是语法,更是对业务语义的理解。
第三道题难度一下子上来了,考的是窗口函数。题目要求是:给定一个交易流水表 transaction(id, user_id, amount, trans_time),找出每个用户连续三天有交易的日期范围。这题本质上是个gap问题,我用的是经典的分组技巧——用交易日期减去按用户分组的序号,如果日期连续,差值会是同一个值,再按差值分组统计连续天数:
WITH t1 AS ( SELECT user_id, trans_time, DATE_SUB(trans_time, INTERVAL ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY trans_time) DAY) AS grp FROM ( SELECT DISTINCT user_id, DATE(trans_time) AS trans_time FROM transaction ) d ), t2 AS ( SELECT user_id, grp, MIN(trans_time) AS start_date, MAX(trans_time) AS end_date, COUNT(*) AS days FROM t1 GROUP BY user_id, grp ) SELECT user_id, start_date, end_date, days FROM t2 WHERE days >= 3;注意中间的DISTINCT去重,因为同一个人一天可能有多笔交易,如果不去重,计算连续天数会出错。这道题考完我最大的感悟是:窗口函数已经成了数据库岗笔试的标配,它既可以用来排名(ROW_NUMBER、RANK、DENSE_RANK),也可以用来做移动计算(SUM OVER、LAG、LEAD),如果复习时不把窗口函数练熟,遇到这种题会非常被动。
3.2 数据库设计题:订单与库存模型
设计题给的场景是开发一个电商系统,要求设计订单表和库存表,并考虑并发扣库存时如何防止超卖。这道题其实是个经典场景题,既考设计能力又考并发控制意识。
我当时的方案分了三层来讲。第一层是表结构设计,订单表我设计为订单主表+订单明细表两张,主表存订单号、用户ID、订单状态、总金额、创建时间,明细表存订单ID、商品ID、商品名称、单价、数量、小计;库存表设计为 product_id、总库存、已锁定库存、版本号。锁定库存是我特意加的一个字段,目的是支持“下单锁定库存、支付成功扣减库存、超时释放库存”这样一个状态流转,比单纯在总库存上做减法更安全。
第二层是防超卖方案。我重点讲了乐观锁的写法:
UPDATE inventory SET stock = stock - #{count}, version = version + 1 WHERE product_id = #{productId} AND stock >= #{count} AND version = #{version};用UPDATE影响的行数来判断是否抢购成功,如果影响行数为0,说明库存不足或版本冲突,需要重试或返回失败。这种方式比先查再更新更可靠,因为查询和更新之间必然存在时间窗口,两个并发请求可能都查到stock=1,然后同时更新,导致超卖。
第三层是补充了悲观锁方案,也就是SELECT FOR UPDATE。但这种方案在库存热点非常高时,会造成锁等待,性能不如乐观锁。我当时在答案里做了一个对比表格,把乐观锁和悲观锁在并发量、冲突概率、实现复杂度、适用场景几个维度上做了分析,这样既展现了知识面,又显得有条理。设计题答题时不能只画表结构,一定要把为什么这么设计、有哪些备选方案、各方案优劣讲清楚,这种“思考过程”正是笔试官想看到的。
3.3 死锁排查与性能优化案例题
简答题里有一道关于死锁排查与优化的题目,场景大概是:某个表频繁出现死锁,SQL日志显示两个事务分别对两个不同的行(或不同索引)执行UPDATE,最终互相等待。问你会怎么排查和解决。
我的思路分四步。第一步,开启死锁日志,MySQL里通过 SHOW ENGINE INNODB STATUS 可以查看最近一次死锁的详细信息,里面会列出两个事务各自持有的锁、正在等待的锁、以及对应的SQL语句。第二步,根据日志定位到具体的SQL和事务,分析加锁顺序。比如事务A先更新id=1后更新id=2,事务B先更新id=2后更新id=1,这种循环等待就是典型的死锁成因。第三步,从业务层面统一加锁顺序,让所有事务都按照相同的顺序访问资源,从根源上消除循环等待。第四步,如果业务层面无法统一顺序,可以尝试降低隔离级别、使用索引减少锁范围,或者把大事务拆成小事务,减小持有锁的时间窗口。
这道题我答完比较有信心,因为它不是纯理论,而是一个实操性很强的排查思路,而且每一步都有对应的工具和命令。后来我在准备面试时还补充了一个细节:SHOW ENGINE INNODB STATUS 里的LATEST DETECTED DEADLOCK段只会显示最近一次死锁,如果想收集更多死锁信息,可以把innodb_print_all_deadlocks参数打开,让所有死锁都记录到错误日志里。这个细节很多教程不会提,但实际排查时非常有用。
4. 热点方向与拓展题:数据库从业者的视野题
4.1 国产数据库趋势与选型考量
笔试最后有一道简答题提到国产数据库的选型。题目核心是:如果公司要做数据库国产化替换,你作为数据库工程师会从哪些角度评估一款国产数据库?这道题很能看出一个人对行业趋势的敏感度。
我当时的分点是这样组织的:第一,兼容性。需要重点评估它与原有数据库(尤其是Oracle和MySQL)在SQL语法、存储过程、触发器等对象上的兼容程度,这直接决定了应用侧改造的工作量。第二,高可用和容灾能力。是否支持主备切换、多副本同步、跨机房容灾,以及切换过程中RPO和RTO能达到什么水平。第三,性能与扩展能力。在OLTP场景或OLAP场景下表现如何,能否通过水平扩展解决单机瓶颈。第四,生态和运维成熟度。是否有完善的监控工具、备份恢复工具、迁移工具,社区活跃度和官方支持力度如何。第五,团队技术储备和人才市场情况。即便产品再好,如果招不到熟悉这个数据库的人,长期维护风险会很大。
这里我专门提到了达梦数据库和人大金仓这样的老牌国产数据库,也提到了开源的TiDB、OceanBase和GaussDB等。说实话,这个领域在近几年变化非常快,原本自己比较陌生的产品现在也都有了成熟的大规模落地案例,所以这类题不要求你深入使用过每一款产品,但至少要知道它们的大致定位和差异。比如OceanBase在金融行业OLTP场景落地比较多,TiDB更强调HTAP和云原生,GaussDB在政企市场结合生态来推。答题的时候如果能举例说明某款产品的典型应用场景,会显得更有说服力。
4.2 时序数据库与向量数据库的兴起
除了传统关系型数据库的话题,试卷里还出现了“时序数据库”相关的一道选择题。它问的是典型的时序数据库使用场景是什么,选项包括监控指标采集、交易记录存储、用户画像管理、全文检索。正确答案显然是监控指标采集,因为时序数据本质上是一条条带时间戳的指标记录,在物联网传感器数据、服务器监控指标、金融行情数据里非常常见。
这个题虽然简单,但它背后的趋势值得展开聊聊。时序数据库的代表产品有InfluxDB、Prometheus、TDengine、TimescaleDB等,它们的核心设计理念是围绕时间维度做优化:按时间分区存储、数据保留策略自动清理过期数据、针对时间范围查询做特殊索引。相比用MySQL硬扛监控数据的方案,时序数据库在写入吞吐量和查询性能上都有数量级的优势。我当时在答案里还提到了TDengine这个国产时序数据库,它在物联网场景下用了超级表+标签模型,设计思路和传统时序数据库有所区别,这种“加分项”能让阅卷人看出你不是只背概念,而是有实际认知。
还有一道涉及向量数据库的题目,问的是向量数据库最适合的是什么业务场景。答案是相似度检索,典型应用包括以图搜图、推荐系统的向量召回、大模型时代的RAG(检索增强生成)等。当时大模型正好是最热的技术话题,向量数据库也顺势火了一把,像Milvus、pgvector、Chroma、Weaviate这些项目我都有所了解。这道题考得不算深,但它是一个信号:数据库岗的笔试已经不再局限于SQL和事务,而是开始考察你是否有技术视野,是否关注到传统数据库之外的新兴存储形态。
4.3 数据库同步、备份恢复与数据一致性
关于数据库同步的题目在试卷里也出现了,题干是:MySQL主从复制默认使用什么日志来同步数据?答案是binlog,但真正有价值的其实是后面跟的简答题:如果主库和从库数据不一致,你会怎么排查和修复?
关于这条,我复盘时整理了完整思路。先说明排查步骤:比较主从的binlog位置或GTID是否一致,通过SHOW MASTER STATUS和SHOW SLAVE STATUS查看复制状态;检查从库是否有SQL线程报错;使用pt-table-checksum工具对比表数据是否一致。如果发现不一致,轻量级的方式是让从库重新同步,也就是从主库备份数据然后在从库恢复;表数量大时,可以考虑用pt-table-sync这种工具修复差异数据,只订正不一致的行,性能开销小很多。
数据库同步这个主题近年来越来越重要,不只是MySQL内部的主从,还包括跨数据库平台的数据同步工具,比如用canal订阅binlog同步到消息队列,再用同步工具写入其他存储系统;或者用DataX、Flink CDC这类工具做异构数据源之间的数据同步。笔试中如果出现这类题目,很可能就是想考察你能否从全局角度看数据一致性问题,而不仅仅是会配一个主从。
备份恢复也是常客。有一道选择题问的是逻辑备份和物理备份的区别,选项里有“逻辑备份是导出SQL语句或数据文件”、“物理备份是直接复制数据文件”、“逻辑备份可以通过管道恢复到异构数据库”、“物理备份通常比逻辑备份更快”。其实四个选项描述基本都正确,但出题人把“逻辑备份是直接复制数据文件”这种错误描述放在了干扰里,所以要特别仔细。备份策略上,我当时是围绕着“每天全备+定期增量+binlog实时归档”的组合来讲,这个方案可以做到任意时间点恢复,是生产环境比较稳妥的做法。
5. 复盘总结与准备建议
5.1 这份笔试题背后的出题逻辑
整份试卷做完,我能比较清楚地感受到出题人的意图:他们想筛选的不是记忆型选手,而是真正理解数据库运行机制、能在实际业务场景中做出合理判断的人。题目设置明显遵循了几条原则:
第一,核心基础题覆盖很全。SQL语法、索引、事务、日志、存储引擎,这些是一个数据库工程师每天都要面对的基础能力,占比最高,而且不是简单背诵而是结合场景去考。第二,场景题强调“为什么”。设计题和性能优化题都要求你给出理由,单纯堆名词给不出高分。第三,加入了一点行业前瞻性内容。国产数据库、时序数据库、向量数据库这些新方向虽然不是重点,但能筛掉完全不关注行业趋势的候选人。
如果你准备参加类似笔试,我建议复习时重点做三件事:一是用一周时间把SQL窗口函数、复杂关联、子查询练到熟练;二是把InnoDB的事务隔离级别、MVCC、锁机制、日志机制彻底理解透,这部分是出题重灾区;三是对主流中间件和数据库产品做一次知识扫盲,不需要深入使用,但至少能说清楚它们解决什么问题、核心特点和适用场景。
5.2 我在备考中踩过的坑
说起备考过程,有几个坑现在回想起来还挺典型的,写出来供大家避雷。
第一个坑是只刷题不看书。前期我用题库刷了不少SQL题,但遇到事务隔离级别和锁的题目时,只能靠记忆答案,稍微换个场景就懵。后来花了两三天时间把《高性能MySQL》里关于锁和事务的章节认真读了一遍,才真正把知识点串起来。笔试中多选题能稳定拿分,靠的就是这一步补课。
第二个坑是忽视了手写SQL的规范性。平时在Navicat或MySQL命令行里写SQL,字段名写错数据库会直接提示,但在笔试系统里,SQL题大多没有自动运行平台,只能靠肉眼检查。我一开始没养成写注释和规范化缩进的习惯,导致好几次自查时看不出逻辑漏洞。后来我强迫自己每一道SQL题都按“先理业务逻辑 → 写框架 → 填充条件 → 检查边界”的顺序来,答题质量明显提升。
第三个坑是时间分配不合理。第一套模拟题做的时候,我在一道复杂度较高的窗口函数题上卡了太久,导致后面的设计题来不及展开来写,得分点大量丢失。从那以后我给自己定下规则:主观题每题最多花15分钟,超过就先写核心思路和要点,后续如果有时间再回来补充,确保每道题都有基本分。
5.3 接下来还可以怎样深入准备
笔试只是秋招的第一关,通过之后迎接你的是更考验综合能力的面试环节。如果笔试中你觉得事务和索引部分比较吃力,那面试前一定要重点准备下面几个方向:
事务方面,要把MVCC实现原理、间隙锁与临键锁、死锁检测与回滚机制这些内容吃透,面试官特别喜欢让你画事务隔离级别的实现示意图,或者给出一个并发场景让你分析会发生什么。索引方面,建议从B+树结构出发,自己推演一遍为什么B+树适合做数据库索引,为什么回表会影响性能,什么是索引下推、什么是ICP优化。数据库设计方面,要多做几个真实场景的建模练习,比如订单系统、权限系统、IM消息系统,把范式设计和反范式设计的取舍想明白。
如果你对国产数据库有兴趣,可以抽出一点时间去官方文档看一下架构概览,比如OceanBase的Paxos多副本协议、TiDB的TiKV分布式事务、达梦数据库的体系结构,不需要深入研究,但至少做到能说清楚它和传统单机数据库在架构上的主要差异。这些在面试时很容易成为加分项,因为很多候选人只在简历上写了“了解国产数据库”,真正能说出点东西的人很少。
还有一个小建议:日常养成看数据库官方文档的习惯。MySQL、PostgreSQL、达梦、人大金仓这些产品的官方文档质量都很高,而且更新及时,比网上那些东拼西凑的博客靠谱得多。我自己备考期间就花了大量时间在文档上,尤其是InnoDB锁和事务的部分,读一遍顶得上刷一百道题。
5.4 我从这次笔试中得到的实际收获
说实话,这次小满秋招数据库岗第一批笔试让我收获最大的不是“掌握了哪些题”,而是让我逼着自己把数据库知识体系重新梳理了一遍。
以前我总觉得做后端开发,数据库只要能增删改查、会写个JOIN、知道加个索引就够了。但真正把数据库岗的笔试当成一场系统的知识体检来做,才会发现自己对很多核心机制的理解其实浮于表面。比如redo log刷盘策略对性能的影响、MVCC在可重复读下的可见性判断、联合索引最左前缀原则背后的实现原因,这些平时写业务代码时很少会深究的问题,恰恰是区分“会用数据库”和“懂数据库”的分界线。
即使最后的结果不一定理想,我也强烈建议准备数据库岗的同学认真对待每一次笔试,考完无论自我感觉如何,都花半个小时把涉及的考点复盘一遍。很多知识点平时看不出差距,只有落到具体题目上,才能暴露你到底有没有真正理解。我就是通过这次笔试后的复盘,发现自己在数据库锁的隔离级别、日志机制这两个方向上还有明显的知识盲区,后来针对性补齐后,面试的技术面明显更从容了。
最后再提醒一句,无论笔试题目变化多少,数据库岗的核心永远是数据本身。你设计的每一张表、写的每一条SQL、选的每一种同步策略,最终都要回到数据的正确性、一致性、可用性上。看清楚这一点,复习的方向就稳了。