
1. 浩鲸2020届数据库笔试的整体画像与出题逻辑前阵子整理移动硬盘翻出当年存的一份资料标题写着浩鲸科技2020届数据库A卷。浩鲸科技这个公司行业内一般叫它浩鲸前身是中兴软创后来阿里云和西班牙电信入股名字也改成了浩鲸科技。它的主要业务集中在电信行业BSS/OSS系统、政企数字化转型这类业务的特点就是数据量大、流程复杂、系统要7x24小时稳定跑着所以它对数据库相关岗位的要求跟纯互联网公司不完全一样。翻完这份A卷我的第一感觉是它考察的方向非常贴合浩鲸的业务场景。卷子里不是那种纯背概念就能拿分的题目也不是那种特别偏门、炫技的算法题而是把重点放在了你在实际系统里到底会不会用数据库这件事上。电信运营商的计费系统、客户关系系统、订单中心这些系统每天要处理千万甚至亿级的流水数据表结构动辄上百个字段SQL写得不讲究轻则接口超时重则把核心表锁死导致整个业务链路瘫痪。所以浩鲸这类公司笔试特别爱考三层东西一是事务并发控制二是索引和SQL优化三是数据一致性与备份恢复。从题型分布看这份卷子大致分成几块单选题大概覆盖数据库基本概念、SQL语法、事务特性多选题和判断题专门挖坑考察对细节的理解简答题集中在索引底层原理、死锁、隔离级别大题是SQL编写和数据库设计。整体难度中等偏上但它好在;——它考察的是你的数据库思维是否成型而不是你背了多少条命令。再看2020届这个时间点那年数据库圈子的风向已经很明显了MySQL是主流应用Oracle在传统行业依然有大量存量PostgreSQL开始抬头国产数据库还在积蓄力量。这份卷子也确实体现了这种格局MySQL和Oracle的内容占大头SQL标准语法必须熟练同时对数据库基础理论的考察很扎实。我见过不少候选人刷了几百道LeetCode式的SQL题一碰到为什么这个SQL走了全表扫描就懵了因为他的学习路径里根本没有理解优化器怎么工作这一环。这份卷子恰恰就是在筛选这样的人。2. 高频考点热词盘点从热搜词看命题侧重把题目跟最近数据库方向的热搜词对照着看会发现一个有意思的现象当年卷子里的核心知识点跟现在社区里大家讨论最多的问题高度重合。像数据库增删改查数据库死锁索引优化数据库同步工具数据库设计国产数据库这些词在当年的笔试卷和现在的面试题里都是高频词只是侧重点和考察深度不同。2.1 增删改查不是送分题是陷阱题很多人觉得增删改查是入门内容但这份卷子里的相关题目恰恰说明越是基础的东西越能拉开差距。比如它考了一道这样的题一张订单表里没有主键只有几个普通索引要把某条记录的状态字段从1改成2问这个UPDATE语句在InnoDB存储引擎下会发生什么。不少人第一反应就是把那条记录改一下但实际执行逻辑是InnoDB会根据条件扫描索引找到对应的聚簇索引记录先对记录加X锁然后修改同时生成UNDO日志如果表上有二级索引还要同步更新二级索引。如果你没有主键InnoDB会使用第一个非空唯一索引如果连这个都没有它会在后台生成一个6字节的ROWID作为隐式主键。这一系列动作少想一步后面的索引维护、锁竞争、复制延迟都可能出问题。再比如它问你DELETE和TRUNCATE有什么区别这个题几乎年年有但它不满足于让你回答一个是删行一个是清表。它会继续追问TRUNCATE能不能回滚在什么隔离级别下两个并发事务分别对同一张表执行DELETE和TRUNCATE会发生什么这就把思考维度从语法层面拉到了事务和元数据锁层面。我建议所有准备笔试的人把增删改查背后涉及的锁、日志、索引维护逻辑都过一遍而不是只背SQL写法。2.2 死锁笔试必考但几乎没人能讲透数据库死锁是这个圈子永远的热搜词也是这份卷子的重点。它考的方向很实在给你两个事务的SQL序列让你判断会不会死锁死锁发生在哪一步MySQL是如何检测和处理的。这类题说白了就是考你锁的兼容矩阵和加锁顺序这两个概念有没有真正理解。举个例子表结构是t(id PK, user_id, amount, KEY idx_user(user_id))事务A先执行 UPDATE t SET amountamount10 WHERE user_id100;事务B先执行 UPDATE t SET amountamount20 WHERE user_id200;然后A再执行 UPDATE t SET amountamount5 WHERE user_id200;B再执行 UPDATE t SET amountamount15 WHERE user_id100;。这两个事务在最低的读已提交隔离级别下是不会死锁的因为每条语句执行完就释放了不匹配条件的记录锁但如果在可重复读下间隙锁和临键锁的存在会让死锁发生概率显著提高。这道题考的就是你有没有意识到隔离级别对加锁范围的影响很多人只在背RR解决幻读这个结论却不知道RR为了杜绝幻读引入了临键锁而这恰恰是大量死锁的来源。笔试复习到这个层次才算过关。2.3 数据库同步与迁移业务系统里躲不开的必修课热搜词里有数据库同步软件数据库同步工具当时这份卷子没直接考工具名但它问了主从复制延迟怎么解决binlog有哪些格式、各自有什么优缺点本质就是在考察同步机制的理解。主从复制延迟这个问题在电信行业尤其严重因为浩鲸的系统里经常有大批量报表任务一个大的聚合查询跑在从库上直接把从库CPU打满主从延迟瞬间飙到几秒甚至几十秒前端运营人员的工单列表就一直转圈。试卷里给出的场景很典型一个主库两个从库其中从库A承载报表查询从库B承载线上业务的读流量某天从库A延迟急剧升高让你分析原因并提出方案。通常的排查链路是先看从库的SQL线程状态确认是不是有一条大事务在回放然后看IO线程是否正常确认主库的binlog有没有及时传到从库的中继日志里最后看从库的硬件指标确认是不是磁盘IO或CPU遇到了瓶颈。解决方案不外乎并行复制、把大查询拆小、用独立的备库做报表。如果笔试里能写出从现象定位到根因分析再到解决方案的完整链路这题的得分会明显高于只写加并行复制的人。3. 事务、隔离级别与MVCC这份卷子最深的理论区3.1 事务ACID没那么简单它考察的是每个特性的实现机制关于事务的考察这份卷子不走背出四个特性这条路它反着来告诉你一个具体的故障场景问你事务的哪个特性保障了数据最终一致。比如一个转账事务把钱从A账户扣掉结果还没来得及给B账户加钱数据库进程崩溃了重启后数据是什么状态这考的是原子性但追问一句原子性是通过什么机制实现的答案指向UNDO日志和回滚段。再比如某事务在可重复读下两次查询同一行数据第二次查询读到了自己被修改过的值这算不算隔离性问题很多人纠结其实这完全正常因为一个事务自己的修改当然对自身可见它不符合脏读的定义因为脏读指读到了别的未提交事务的修改。ACID这个概念如果不落到具体由哪个组件和哪种日志保障的层面遇到这种变体题很容易翻车。我给自己的复习原则是每背一个概念必须用一句话说清楚它对应的底层实现。原子性对应UNDO持久性对应REDO隔离性对应锁和MVCC一致性是这个系统所有机制配合的最终结果。这四个点串起来事务类题目基本能覆盖八成。3.2 隔离级别之间的边界脏读、不可重复读、幻读的精确差异这份卷子在隔离级别上出了不止一道题而且全是场景判断题。脏读、不可重复读、幻读这三个现象看起来是三条定义实际上考的是你能不能识别一段SQL时序里到底发生了哪种现象。我见过很多人把不可重复读和幻读混在一起其实核心区别在于不可重复读针对的是同一条记录的两次读取结果不一致幻读针对的是同一个范围的两次查询返回了不同数量的行。卷子里有个经典反例在可重复读隔离级别下事务A先SELECT了某个范围的数据事务B往这个范围插入了新记录并提交事务A再次SELECT时居然没看到新记录于是用UPDATE把范围内所有旧记录的某个字段改了。由于快照读和当前读的机制差异事务A其实把事务B插入的那条新记录也锁住了。这个现象在MySQL的InnoDB下叫做半一致读如果题目不点破特别容易让人以为可重复读彻底解决了幻读。事实上InnoDB是靠临键锁和间隙锁在索引层面阻止了新记录插入到范围内才实现了真正意义上的可重复读下无幻读但这种实现方式也不是无条件的它只在使用了正确的索引访问路径时才有效。3.3 MVCC的快照读与当前读为什么你的快照读看不到别人已提交的数据MVCC是事务部分的核心也是这张卷子拉开分数的地方。它用了一道题来考快照读和当前读的区别一个事务在可重复读下做了一次普通SELECT之后另一个事务提交了新数据再之后这个事务里再执行一条UPDATE语句发现它能更新到刚才别人提交的那条记录问为什么。这道题直击MVCC的机制本质普通SELECT是快照读用的是事务开始时的ReadViewUPDATE、DELETE、SELECT FOR UPDATE是当前读读的是最新已提交版本并加锁。可重复读下快照只生成一次所以快照读不会看到新数据但当前读不会受这个限制。这个知识点在实际系统里的影响非常深远。业界的经验是在一个事务里别先做快照读再做当前读除非你明确知道自己在干什么。否则你基于快照读的结果去更新数据很容易产生逻辑上的数据不一致。比如一个事务里先SELECT余额是100然后业务判断余额足够就执行UPDATE但实际上另一个事务已经把这个余额改成50了你的UPDATE当前读会把50加锁并改掉而你业务层判断用的数据还是100。这就是典型的并发更新问题如果业务上不允许这种情况就要在事务一开始就用SELECT FOR UPDATE把锁加上。4. 索引与SQL优化笔试大题的必争之地4.1 索引底层原理B树为什么能统治关系型数据库浩鲸这份A卷的索引部分没有一上来就考B树而是从什么场景下索引失效切入再问到为什么最左前缀原则会存在。但如果你不懂B树的结构这两道题都答不透。B树跟其他树结构最大的区别在于三点数据只存在叶子节点叶子节点之间用链表相连非叶子节点只存索引键和指针。这个设计让它在磁盘IO场景下特别占优因为树的层高很低三层B树就能存千万级别的数据查询一个记录只需要几次磁盘IO。同时叶子节点链表让范围查询非常高效从小到大扫一遍就行。MySQL默认的InnoDB引擎索引组织方式是聚簇索引主键的B树叶子节点直接存整行数据二级索引叶子节点存的是主键值所以通过二级索引查数据需要回表先查二级索引得到主键再回聚簇索引找整行。这个机制解释了为什么主键要尽量用自增整数因为如果主键是UUID这种随机字符串每次插入新记录时B树都要大量分裂调整性能很差。索引失效的问题也大多要从这个结构去理解条件列上做函数操作相当于你把B树里存的键值都改了一遍树本身的结构没法用了优化器只能放弃索引走全表扫描。4.2 从执行计划反推SQL写法EXPLAIN到底在看什么笔试里的大题直接给了一条慢SQL的EXPLAIN输出让你指出问题并优化。这张表的EXPLAIN结果里type列是ALLExtra列是Using where意思是全表扫描没有用到任何索引。优化方向一般分两步第一步看WHERE条件、ORDER BY、GROUP BY涉及的列看看能不能建联合索引第二步看SELECT的列是否在索引里如果只查几个列可以考虑覆盖索引避免回表。但真实业务里很少这么简单。比较典型的坑是你给一张表建了联合索引(company_id, status, created_at)然后有一个查询条件是WHERE company_id? AND created_at BETWEEN ? AND ?这时候最左前缀原则要求必须从company_id开始created_at是第三个列而中间跳过了status那这个B树最多只能利用company_id这一列来定位created_at的过滤是在回表后逐行进行的。所以正确做法是让联合索引的列顺序跟查询条件的过滤粒度对齐区分度高的列放前面范围查询的列放最后。这个区分度和列顺序的问题在所有数据库笔试题里都属于高频中的高频。4.3 一条具体慢SQL的优化全过程从全表扫描到覆盖索引卷子最后的大题里有这么一条SELECT id, user_id, amount FROM payment WHERE status0 ORDER BY create_time DESC LIMIT 50;。表里数据量是2000万行status0的记录占比大概40%。如果直接在status上建索引比例太高优化器依然会选择全表扫描因为扫描索引后再回表的成本比全表扫还高。如果不建索引每次执行就是全表扫描加filesort耗时大概2秒多。我当时给的优化思路是把查询改成覆盖索引。建一个联合索引(status, create_time, id, user_id, amount)让查询需要的所有列都在索引里这样就不需要回表而且由于status用了等值条件create_time可以在索引内有序排列LIMIT 50只要顺着索引往前扫50条就行。这条SQL从2秒降到了几十毫秒效果非常明显。但这个方案也有代价每次INSERT、UPDATE都要维护更大的索引写入性能会下降。所以笔试里如果你能把优化方案和代价分析都写出来得分会比只写建索引高一个档次。5. 数据库设计的实操维度不只画ER图那么简单5.1 三大范式的工程取舍规范化与反规范化的平衡点数据库设计部分卷子出了个需求一个简单的订单系统要求设计订单表、订单明细表、商品表。表面上是考察建表能力实际上考察的是范式理解和业务场景的权衡。订单系统这种OLTP场景通常要遵守第三范式把客户信息、商品信息、订单信息拆开避免数据冗余因为冗余会导致更新异常和一致性风险。但如果你做过电商或电信计费系统就会知道订单表往往存了商品名称的快照字段而不是统统去联表查商品表。原因很简单商品名称和价格可能变但订单快照里的信息不能被历史变更影响。这就是一种有意为之的反规范化设计。笔试中问是否允许冗余时如果能答出冗余的目的是用空间换时间且必须通过应用层保证冗余字段和源数据的一致性这个回答会体现出工程经验。5.2 主键策略自增ID、UUID还是分布式ID这张卷子还考了主键选择。自增ID在单机数据库里性能好但分库分表后会出现重复或需要改造主键的问题。UUID适合分布式环境生成但作为InnoDB聚簇索引主键时会导致页分裂严重写入性能下降。所以现在业界的主流做法是使用雪花算法或类似的分布式ID生成器既能保证全局唯一、趋势递增又不会像字符串型UUID那样破坏索引结构。笔试答这类题不要只罗列优缺点要结合场景给出结论。比如浩鲸这类电信BSS系统全国有多个分中心每个分中心都有独立的数据库客户ID如果各库自增合并到总部就会撞主键。这时候引入分区键加上雪花ID是常见方案。你答出这个层次阅卷人会知道你真的处理过分库分表的数据合并问题。5.3 从ER图到物理建表字段类型与约束的细节试卷里还要求根据业务描述设计表和字段类型。这里有个容易被忽略的细节DECIMAL和FLOAT的区别。在涉及金额的场景必须用DECIMAL因为FLOAT和DOUBLE是浮点数二进制的表示方式天然无法精确表示所有十进制小数做加减乘除会产生精度误差。电信计费全是钱分毫都不能差所以金额字段务必用DECIMAL(10,2)这种定点数类型。还有字符集和排序规则的选择。如果表里涉及到中文等多语言字符必须用utf8mb4而不是utf8因为MySQL的utf8只是utf8mb3的别名最多存3字节像emoji这种4字节字符会存不进去。排序规则方面如果你对大小写不敏感可以用utf8mb4_general_ci或utf8mb4_unicode_ci具体差异是unicode_ci的排序更符合Unicode标准但性能略慢。这些细节是实践中最常踩的坑笔试也特别容易出判断题。6. 周边生态与技术趋势工具链和国产数据库的进场6.1 数据库管理工具的选型命令行之外的另一条腿热词里有dbx数据库工具db browser for sqlitenavicat数据库管理工具这些词说明大家对数据库的使用离不开工具链。但我想借此说一个观点工具是放大器你的SQL能力和数据库原理理解才是基础。你用图形化工具连接数据库点一下执行看到的只是结果集背后执行计划怎么走的、走没走索引、锁等待多少毫秒这些信息才是优化SQL的关键。所以我个人建议在笔试备考阶段尽量用命令行去操作MySQL或PostgreSQL多用EXPLAIN、SHOW ENGINE INNODB STATUS这类命令逼自己养成看原始信息的习惯。等原理都通了再用图形化工具提高日常效率也不迟。对于SQLite的加密问题比如热搜里有db browser for sqlite 怎么打开加密的数据库答案是SQLite本身没有内置加密常见的是SQLCipher。SQLCipher是SQLite的加密扩展通过256位AES加密整个数据库文件要打开它必须用支持SQLCipher的客户端并提供密钥。这个场景在移动端和小型桌面应用中非常常见笔试如果问你数据库文件怎么保证安全这其实是一个很好的思路。6.2 从Oracle到人大金仓、达梦国产数据库的迁移与适配2020年之后国产数据库的势头越来越猛热搜词里达梦数据库人大金仓数据库dockergaussdb频繁出现说明这个领域已经是事实上的行业热点。达梦数据库在架构上兼容Oracle的很多语法和特性存储过程、包、游标等都有对应实现所以从Oracle迁移到达梦的成本相对低一些。人大金仓KingbaseES则更偏PostgreSQL系它的SQL语法、JSON支持、扩展机制跟PostgreSQL很像所以如果你熟悉PostgreSQL上手KingbaseES会很顺。GaussDB是目前讨论度比较高的分布式数据库它跟openGauss同源在华为云生态里地位非常高很多政企客户在做核心系统改造时都会评估它。这类数据库的笔试题往往不会直接考你用某种国产数据库写SQL而是考迁移方案怎么设计。比如从Oracle迁移到达梦需要处理几个关键差异一是数据类型映射VARCHAR2、NUMBER、DATE这些要对应到达梦的类型二是内置函数差异NVL、DECODE、ROWNUM这些Oracle特有的函数要改成达梦支持的写法三是分页查询Oracle用ROWNUM达梦也兼容了ROWNUM但如果迁移目标是PostgreSQL系的KingbaseES就要改成LIMIT和OFFSET。这些跨数据库迁移的细节笔试如果考到是真正拉开经验差距的题。6.3 数据库同步工具与MCP生态新的连接方式数据库同步这块热词里数据同步软件数据库同步工具workbuddy通过mcp直接访问数据库非常亮眼。MCPModel Context Protocol是最近很火的协议它让AI助手可以通过标准化的方式去访问外部数据源。比如WorkBuddy这类工具通过MCP连接数据库后业务人员就能用自然语言向AI提问查一下上个月订单量排名前十的商品AI会把问题转成SQL查询数据库后把结果返回给用户。这套东西看起来神奇但底层依然是数据库的连接管理、SQL执行、结果集处理这些基本功。如果连基本的SQL都写不明白工具再好也帮不了你。数据库同步工具的实际场景更多还是在主从复制、双活数据中心、异构数据库迁移这些层面。现在常用的开源同步工具比如Canal、Debezium、DataX、Flink CDC各有侧重。Canal主要监听MySQL的binlog把变更日志导入到消息队列或者其他存储用来做缓存更新、异构同步、数据归档。Debezium是通用的CDC框架支持MySQL、PostgreSQL、Oracle、SQL Server等配合Kafka Connect使用可以构建实时数据管道。DataX是阿里开源的离线同步工具适合大数据量的批量导入导出。Flink CDC则把实时同步和流式计算结合在一起可以在同步的过程中做清洗转换。笔试或面试时如果你谈数据同步能把在线补数用DataX、实时流同步用Canal或Debezium、复杂加工用Flink CDC这个选型逻辑讲清楚基本就是加分项了。7. 按照这份卷子倒推的备考路线与答题节奏7.1 先把核心五件套吃透再刷题做数据库笔试备考很多人一上来就疯狂刷SQL题但数据结构没吃透刷再多也容易卡壳。根据浩鲸这份A卷的考点分布我建议的复习顺序是第一事务与隔离级别重点是ACID的底层实现、四种隔离级别、MVCC机制、锁分类和死锁。第二索引原理重点是B树结构、聚簇索引和二级索引、回表、覆盖索引、索引失效场景、执行计划。第三SQL语法与调优重点是增删改查的细节、聚合函数、子查询、JOIN的底层原理和适用场景、LIMIT分页的深层优化。第四数据库设计重点是范式、主键策略、字段类型选择、字符集、约束设计。第五备份恢复与高可用重点是binlog、redo log、undo log的区别与作用、主从复制、集群架构、数据迁移。这五块内容每一块都要能形成概念定义-底层机制-典型场景-常见坑点-实战优化的完整闭环。做到这个层次不管是浩鲸还是其他公司的数据库笔试大概率都能应付。7.2 考场上的答题顺序和时间分配这份卷子的题量不算大但陷阱多所以我建议先快速扫一遍所有题目把简单的概念题和SQL语法题先做掉把需要深度推理的题目留到后面。一般来说选择题和判断题控制在20分钟以内简答题控制在30到40分钟SQL大题和数据库设计题留足40分钟。如果一道题想了三分钟还没有明确思路先跳过别在单题上死磕。SQL大题特别容易失分是因为候选人只写了主SELECT语句漏了索引设计、数据初始化、边界情况处理。我的习惯是写SQL之前先花30秒在草稿上确认表结构和数据关系写完之后再花30秒检查WHERE条件里有没有列上做了函数处理、JOIN的关联列有没有索引、ORDER BY有没有配合索引顺序。这些检查动作虽然简单但能有效避免最常见的低级错误。7.3 我踩过的坑笔试里最容易被扣分的四个细节第一个坑是分页查询的深翻页。LIMIT 100000, 20看起来很简单但MySQL要扫过前面的100000条记录再扔掉代价很高。笔试题如果给一个大数据量的分页场景答案就不能只有LIMIT要想到游标分页、延迟关联、或者把排序字段改成覆盖索引里的列。第二个坑是COUNT()和COUNT(列名)的区别。COUNT()统计的是所有行数COUNT(某列)统计的是该列非NULL的行数。在MySQL里COUNT(*)经过优化后性能反而比COUNT(1)更好这在很多人的认知之外笔试判断题经常拿这个做文章。第三个坑是UPDATE语句的WHERE条件没走索引。一旦全表扫描InnoDB会给所有扫描到的行加锁哪怕最终不更新的行也加了锁这会放大锁范围严重时直接把整张表锁住。在InnoDB里DELETE和UPDATE的加锁范围跟WHERE条件的索引选择性强相关如果选择性差锁的范围就可能大得离谱这在线上是重大事故级别的隐患。第四个坑是字符集不一致导致的隐式转换。两个表关联字段如果一个是utf8一个是utf8mb4MySQL会在比较时把utf8转成utf8mb4这个转换会导致该字段上的索引失效。笔试中很容易出这种细节判断题项目里也是特别折磨人的问题。8. 如何把这些经验转化成你自己的知识体系最后说点比较个人的体会。数据库这个东西知识点非常多但底层逻辑其实是相通的。你理解了页和B树就理解了为什么索引快、为什么主键用自增、为什么select最左前缀失效你理解了日志和锁就理解了为什么事务需要隔离级别、为什么死锁和主从延迟会发生。所以我不建议大家分散地去记零散的知识点而是建议每学一个概念都问一句它是为了解决什么问题而存在的这样你的知识就是一张网而不是一堆碎片。浩鲸这份2020届数据库A卷放到现在看考察的核心能力依然没有过时。相反随着数据量变大、系统越来越复杂数据库基础能力的重要性反而更高了。我见过太多只会写CRUD、一遇到数据库性能问题就束手无策的开发人员也见过不少能把一条慢SQL优化到毫秒级、能把整个数据库迁移方案讲得明明白白的工程师后者的成长路径通常都有很扎实的底层原理做支撑。如果你正在准备数据库方向的笔试或面试我的建议很简单别急着刷题先把MySQL的InnoDB存储引擎、事务、索引、日志这几块内容通读一遍然后对照着这篇文章里的考点一个一个过确保每个点都能用自己的话讲清楚并且能举出实际例子。这个基本功打好了后续你去看Oracle、PostgreSQL、达梦、GaussDB这些会发现很多概念是相通的。最后分享一个小技巧。我复习时有个习惯每学完一个知识点就在一张卡片上画一个小型场景图包含表结构、SQL语句、执行过程、结果。比如学完MVCC就画一个事务A和事务B读写冲突的快照读场景学完死锁就画一个两条UPDATE互相等锁的时间线。这些卡片攒到一定数量后我在面对笔试场景题时脑子里会迅速匹配到对应的卡片答题速度和准确率都明显提升。这个办法你也可以试试比闷头看书刷题高效得多。