简介压缩包为2025全国大学生计算机系统能力大赛第五届OceanBase数据库大赛相关资源合集面向数据库方向竞赛选手与OceanBase学习者。内容涵盖C/C头文件与源程序、Python辅助脚本、JSON与YAML配置文件、Markdown说明文档等共2000个文件整体尺寸约113.94MB目录结构贴近实际工程布局便于按模块查阅与二次开发。目前已有50人学习浏览。通过这份资料可系统接触大赛相关项目代码与配套设施例如Minio对象存储相关的构建脚本、CMake配置及工具集有助于快速熟悉OceanBase周边生态和比赛环境搭建为备赛或研究数据库内核提供体系化的参考。1. 2025 OceanBase 数据库大赛比的不是写 SQL而是把数据库跑稳的能力2025 全国大学生计算机系统能力大赛-第五届 OceanBase 数据库大赛对多数队伍来说不是一场 SQL 背题赛而是一场环境治理战。报名时觉得自己会增删改查就能上场真到模拟题才发现题目丢给你一套分布式数据库要先装起来、灌数据、从日志里找出慢查询为什么慢再在压测工具面前把延迟打下去。赛事筛选的逻辑很直接——你能不能把一个数据库系统从部署、调优、排错到结果验证完整走一遍。它适合正在准备校招、想做内核或研发方向以及想摆脱只会写 CRUD 的学生。备赛过程不需要你成为内核专家但需要你对数据库的运转方式有真实的体感。2. 备赛先备环境用 Docker 装最小 OceanBase 实例的三个落地动作2.1 为什么不上来就照着生产部署文档走网上搜 OceanBase 数据库安装教程搜出来的一多半是生产环境完整链路多台机器、observer、obproxy、OCP 管理面光前置检查就能折腾一下午。对备赛来说这个投入不划算。比赛考的是你对数据库本身的理解不是你会不会搭一整套运维系统所以我的建议是直接用社区版镜像起一个单机最小实例。社区版容器的最小实例能把 observer 进程、系统租户、内部视图都给你备齐SQL 行为和生产环境基本一致唯一区别是少了多节点的数据分布效果。备赛前期用这个环境练执行计划、调参数、跑压测完全够用。等进入决赛前再切换到多节点环境去熟悉跨节点调度和分布式执行计划这是后话。2.2 用 Docker 把实例跑起来启动参数与首次启动的等待常见做法是拉取官方社区版镜像后直接跑容器。不同版本的环境变量名可能有差异以你拉到的镜像说明为准我这边常用的启动命令长这样docker run -d --name oceanbase-lab \ -p 2881:2881 \ -e MODEmini \ -e OB_MEMORY_LIMIT8G \ -e OB_LOG_DISK_LIMIT10G \ oceanbase/oceanbase-ce这里MODEmini表示用一个最小规格完成初始化适合比赛环境OB_MEMORY_LIMIT控制整个实例的内存预算8G 是经验值低于 4G 时后续压测会频繁触发内存转储性能曲线非常难看OB_LOG_DISK_LIMIT是日志盘配额很多人忽略它等压测写日志把配额耗尽才发现数据写不进去了。容器启动后不要立刻连数据库。首次初始化要跑一两分钟端口虽然监听了内部系统租户可能还没就绪。看日志等它docker logs -f oceanbase-lab当输出里出现类似 boot success 的关键字后再执行客户端连接。这一步能避免很多“明明启动了却连不上”的翻车现场。2.3 连接串、租户与连接池OceanBase 与 MySQL 最大的使用差异先解释一个让新手绕圈子的概念OceanBase 里用户名的完整写法是usertenant你连接的也不是“某个数据库实例”而是某个租户。默认的sys租户是管理租户业务表要建在你自己创建的租户里。用系统租户登录obclient -h127.0.0.1 -P2881 -urootsys -p然后创建一个最小业务租户这里以通用大版本语法为例CREATE RESOURCE UNIT u1 MAX_CPU2, MEMORY_SIZE2G; CREATE RESOURCE POOL p1 UNITu1, UNIT_NUM1; CREATE TENANT t1 RESOURCE_POOL_LIST(p1);MEMORY_SIZE是这个租户能用的内存上限UNIT_NUM1在单机环境下表示只分配一个资源单元。比赛环境如果机器内存紧张1G 也能跑但压测结果会很难看。接着登录业务租户建库建账号obclient -h127.0.0.1 -P2881 -uroott1 -pCREATE DATABASE race_db; CREATE USER app IDENTIFIED BY app_pass; GRANT ALL ON race_db.* TO app;到这里你已经把一个最小 OceanBase 环境跑起来了。备赛阶段所有 SQL 练习和压测都基于这个环境做。这块还牵扯到连接池配置。OceanBase 兼容 MySQL 协议很多驱动默认会把它识别成 MySQL于是就会出现couldnt deduct database type from database product name oceanbase这类报错本质是驱动不认识这个产品名。常见做法是在连接池里显式指定驱动类型或者使用官方提供的客户端组件。另外连接池的 maxActive 不要拍脑袋调大它必须和租户允许的连接数上限匹配否则压测时只会制造一堆 TIME_WAIT 连接把端口池打满。3. 慢查询优化从执行计划里找出压测扛不住的原因3.1 造数一条 SQL 生成百万行订单数据学习阶段不需要等比赛给数据自己造数才能反复验证。先建一张订单表CREATE TABLE t_order ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, amount DECIMAL(10, 2) NOT NULL, status TINYINT NOT NULL, create_time DATETIME NOT NULL );注意暂时不要建索引造数阶段索引会明显拖慢插入速度等数据灌完再补索引。造数我一般用一条 INSERT SELECT 完成SET i 0; INSERT INTO t_order (id, user_id, amount, status, create_time) SELECT i : i 1, MOD(ROUND(RAND(i) * 1000000), 100000), ROUND(RAND(i) * 1000, 2), MOD(i, 5), DATE_SUB(NOW(), INTERVAL MOD(i, 365) DAY) FROM information_schema.columns a CROSS JOIN information_schema.columns b LIMIT 1000000;这段 SQL 的原理是用系统自带的元数据表做笛卡尔积把行数撑到百万级。MOD(i, 5)让 status 分布在 0 到 4DATE_SUB把时间散到过去一年。如果你拉到的版本对 information_schema 的行数限制比较严格一次插不到百万就拆成几个批次分批执行。造数阶段出现速度慢很正常因为每条 INSERT 都走事务。可以把 autocommit 打开或者每 5000 行手动提交一次别让单条超大事务长时间占住内存。3.2 让执行计划现形EXPLAIN 之后先盯这三个字段有了数据下面这条 SQL 在没有索引时会非常典型地慢SELECT user_id, COUNT(*) AS cnt, SUM(amount) AS total FROM t_order WHERE status 1 AND create_time 2025-01-01 GROUP BY user_id ORDER BY total DESC LIMIT 10;先看它的执行计划EXPLAIN SELECT user_id, COUNT(*) AS cnt, SUM(amount) AS total FROM t_order WHERE status 1 AND create_time 2025-01-01 GROUP BY user_id ORDER BY total DESC LIMIT 10;执行计划里我一般先盯三个地方。第一个是TABLE SCAN它代表全表扫描百万行数据量下所有行都要过一遍第二个是SORT排序如果没走索引会把中间结果放到内存甚至落盘第三个是HASH GROUP BY它在内存里建哈希表聚合数据量大时内存消耗会直接拉高。对应的解决手段是建立一个覆盖索引让过滤、分组、排序需要的列都进索引CREATE INDEX idx_status_ct ON t_order(status, create_time, amount, user_id);索引建完后再跑一遍 EXPLAIN把前后两次输出对比。一个负责任的优化流程到这里才算走完一半因为索引建了不代表优化器会用它。数据量小、统计信息旧、过滤条件选择性差都可能让优化器继续选全表扫。所以下一步是更新统计信息ANALYZE TABLE t_order COMPUTE STATISTICS;这条命令在比赛场景里非常容易被忽略。很多人“加了索引没效果”八成不是索引本身的问题而是统计信息还是旧数据优化器根本没意识到新索引值得走。备赛时还有一类必调参数是超时。压测脚本跑得久一条 SQL 执行时间超过默认阈值就直接报错失败SET GLOBAL ob_query_timeout 30000000; SET GLOBAL ob_trx_timeout 30000000;单位是微秒这里设置的是 30 秒。这个值只建议在比赛环境调大生产环境照抄会掩盖真正有问题的慢 SQL。3.3 从单条 SQL 到整库压测三个先调的内存与日志参数单条 SQL 优化完下一步是看整体压测。这时候大部分问题不在 SQL而在实例配置。我自己比赛时会先确认三个参数参数作用备赛建议OB_MEMORY_LIMIT实例可用内存总预算至少 8G太小会频繁转储OB_LOG_DISK_LIMIT日志盘配额写满即报错压测前给足建议 10G 以上ob_query_timeoutSQL 执行超时压测环境调到 30 秒以上内存参数的调整会直接反映在压测曲线的稳定性上。内存给得太小数据写完触发转储压测过程会出现周期性的性能毛刺看起来就像有人在捣乱其实是内存不够用。日志盘参数更隐蔽。普通文件系统还有空间但 OceanBase 的日志盘是独立配额写满后任何写入都会报错。备赛时我会在启动容器阶段就一次给足避免中途调整引发一连串配置问题。4. 从初赛到决赛的交付节奏先跑通、再调优、最后留证据4.1 压测先跑基线把“慢”量化成三个可比较的数字很多队伍一上来就调参数结果调了半天说不清到底有没有变快。我的习惯是先跑一次原始环境的压测拿到三个数字吞吐、并发数、尾延迟。赛题一般会提供压测脚本没有的话就自己写一个简单的循环脚本多跑几轮取中位数#!/usr/bin/env bash set -euo pipefail for round in 1 2 3; do ./bench-run.sh --configconfigs/baseline.conf \ --outputlogs/baseline-$round.log sleep 5 done跑三次而不是一次是因为压测结果受系统噪声影响很大单次数据容易骗人。三次之后取中位数这张基线表就是你后续所有优化的对照系。赛题如果没有明确评分口径我建议盯 p95 而不是平均值。平均值会被少数长尾请求拉高p95 代表大多数用户真实体感评审压测时更接近这个数字。4.2 留证据把每次调整变成一条可回滚的配置记录调优过程中最忌讳的是“我记得我改过什么”。备赛周期短则两周长则两个月中间穿插课程和考试忘记了非常正常。从第一天起就把配置和脚本纳入 git 管理mkdir -p configs logs git init git add -A git commit -m baseline recorded每次改动后提交一次对比就清晰了diff -u configs/tenant-before.sql configs/tenant-after.sql这个 diff 是你赛后复盘最重要的材料。调参为什么有效、哪个改动引入了新问题全靠这些记录。提交结果时我一般带一张表改动QPSp95 延迟CPU基线1200850ms40%加索引2800320ms55%不要只写“我调优了”把压测输出文件、配置文件、前后对比三样一起交评审才有据可查。4.3 决赛多节点环境并发锁与一致性最容易暴露的两个硬边界进入决赛后环境通常从单机变成多节点。这时候单机上调优的经验有一半要作废因为执行计划里会多出跨节点的数据交换SQL 的表现不再由单台机器决定。第一个硬边界是资源单元分布。多节点环境下租户的资源池要尽量覆盖所有节点否则数据全部打在少数节点上热点问题会把整个集群拖慢。常见做法是把资源池的 UNIT_NUM 配成 observer 数量一致让数据相对均匀地打散。第二个硬边界是并发锁。压测并发一高死锁和锁等待就会出现。典型场景是两个事务以相反顺序更新同一组数据互相等对方释放锁最终报 deadlock。解决思路很朴素所有事务都按同一顺序访问主表事务内操作行数控制在几千行以内快速提交不给锁等待留时间。比赛里还常见一类“热点行更新”题目所有并发请求都集中更新同一个计数器行锁竞争直接打到天花板。应对方式也简单把计数器拆成多个分桶 key各桶独立更新读的时候汇总即可。5. 备赛避坑清单5 个让队伍折在赛前的常见问题5.1 现象压测跑着跑着连接全断压测执行到一半所有客户端连接同时断开重连也失败。翻看压测脚本本身没有报错。原因多半是 SQL 执行超时。默认的 query timeout 比较保守压测脚本里的复杂查询一旦执行超过阈值连接会被服务端主动断掉。另一个常见原因是连接池 maxActive 设置超过了租户允许的最大连接数新建连接全部失败。解决方式是把超时调大并检查连接池配置SET GLOBAL ob_query_timeout 30000000; SET GLOBAL ob_trx_timeout 30000000;连接池那一侧把 maxActive 降低到租户允许范围内别让无效连接占满端口。赛后记得把超时调回默认值这个参数在生产环境里不适合长期使用。5.2 现象磁盘空间足够数据却写不进去执行插入时报错类似“no space left on device”但用 df 看磁盘明明还有一大半剩余。原因是 OceanBase 把日志盘和普通数据盘分开管理日志盘配额写满后任何写入操作都会被拒绝即使数据盘还有空间。这个配额在容器环境里由 OB_LOG_DISK_LIMIT 控制在租户维度则由 LOG_DISK_SIZE 控制。解决方式是在启动容器时一次性把日志盘配额给足。已经在跑的环境可以尝试调大资源单元的日志盘配置ALTER RESOURCE UNIT u1 LOG_DISK_SIZE10G;但某些版本对资源单元的修改有在线限制最稳的做法还是回到第一步把环境建对别中途反复折腾。5.3 现象本地毫秒级评审环境却超时同样的 SQL 在本地跑得飞快到评审环境直接超时这类问题最打击士气。原因通常有三个本地数据量太小内存里就装下了评审环境数据分布跨节点统计信息没有更新优化器选了错误的执行计划并行度没有生效查询实际是单线程在跑。解决方式也很明确备赛后期一定要用和赛题接近的数据规模做验证小数据量下“刚好能用”的方案不值得信任。大批量写入后第一时间执行 ANALYZE TABLE 更新统计信息然后看 EXPLAIN 输出里有没有出现跨节点的数据重分布算子。如果出现说明你的查询正在各个节点之间搬运数据这时候才需要评估并行参数是否合理。5.4 现象observer.log 里 timeout 与 retry 刷屏日志文件里出现大量 timeout、retry、lock conflict 关键字压测结果忽高忽低。原因通常是长事务占住锁不释放其他事务一直在等锁等到超时就报错重试。另一个常见来源是驱动关掉了 autocommit 但忘记 commit事务一直处于打开状态。解决方式是把大事务拆小每批 5000 行左右提交一次避免在事务里做跨表大批量更新。同时检查活跃事务把长时间未提交的连接找出来杀掉。压测脚本里如果手动管理事务一定要确保 finally 块里做 commit 或 rollback。5.5 现象参数照网上抄启动直接报错网上教程里的参数抄过来执行时报 unknown variable 或参数格式错误。原因很简单版本不一样。很多参数是某个版本后才支持的还有些只存在于特定版本或企业版功能里社区版并不识别。解决方式是把版本锁定以你安装版本对应的 release notes 和已知限制为准。备赛期间不要频繁升级或降级大版本。容器镜像和配置文件都保留一份本地备份哪天环境弄坏了还能用备份重新拉起来这相当于给自己留了一条后悔药的路径。我从第一次带队伍起就坚持这个习惯镜像、配置、脚本全部存档比赛当天只做复现不做新改动。6. 把调优过程沉淀成 runbook三天后还能复现才是真本事比赛结束后的第三天你还能不能把当时的参数解释清楚这是我觉得备赛最有价值的一个问题。我的习惯是始终把一个赛队的产出当作一个小型交付物来组织目录结构类似race-repo/ README.md configs/ scripts/ logs/ results.mdREADME 里写清楚环境怎么起、数据怎么灌、哪个配置对应哪次改动。scripts 里放压测脚本和数据生成脚本logs 里按时间命名存放每次压测的原始输出。验证方法我也固定下来每次改动后跑三轮压测取中位数对比只看 p95不看平均值结果表里固定记录 QPS、尾延迟、CPU 三个数字。这样每次调参是否有效一眼就能判断。比赛结束前把整套东西跑一遍复现命令bash scripts/setup.sh bash scripts/bench.sh如果这条命令能在一个全新环境里完整跑通你的备赛成果才是扎实的。名次是评审给的但这套可复现的能力是你自己的。希望帮到你。本文还有配套的精品资源点击获取