☰
OceanBase数据库大赛备赛:Docker环境搭建与慢查询性能调优实战
2026/10/3 4:00:32 网站建设 项目流程

简介:压缩包为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 MODE=mini \ -e OB_MEMORY_LIMIT=8G \ -e OB_LOG_DISK_LIMIT=10G \ oceanbase/oceanbase-ce

这里MODE=mini表示用一个最小规格完成初始化,适合比赛环境;OB_MEMORY_LIMIT控制整个实例的内存预算,8G 是经验值,低于 4G 时后续压测会频繁触发内存转储,性能曲线非常难看;OB_LOG_DISK_LIMIT是日志盘配额,很多人忽略它,等压测写日志把配额耗尽才发现数据写不进去了。

容器启动后不要立刻连数据库。首次初始化要跑一两分钟,端口虽然监听了,内部系统租户可能还没就绪。看日志等它:

docker logs -f oceanbase-lab

当输出里出现类似 boot success 的关键字后,再执行客户端连接。这一步能避免很多“明明启动了却连不上”的翻车现场。

2.3 连接串、租户与连接池:OceanBase 与 MySQL 最大的使用差异

先解释一个让新手绕圈子的概念:OceanBase 里用户名的完整写法是user@tenant,你连接的也不是“某个数据库实例”,而是某个租户。默认的sys租户是管理租户,业务表要建在你自己创建的租户里。

用系统租户登录:

obclient -h127.0.0.1 -P2881 -uroot@sys -p

然后创建一个最小业务租户,这里以通用大版本语法为例:

CREATE RESOURCE UNIT u1 MAX_CPU=2, MEMORY_SIZE='2G'; CREATE RESOURCE POOL p1 UNIT='u1', UNIT_NUM=1; CREATE TENANT t1 RESOURCE_POOL_LIST=('p1');

MEMORY_SIZE是这个租户能用的内存上限,UNIT_NUM=1在单机环境下表示只分配一个资源单元。比赛环境如果机器内存紧张,1G 也能跑,但压测结果会很难看。

接着登录业务租户,建库建账号:

obclient -h127.0.0.1 -P2881 -uroot@t1 -p
CREATE DATABASE race_db; CREATE USER 'app' IDENTIFIED BY 'app_pass'; GRANT ALL ON race_db.* TO 'app';

到这里,你已经把一个最小 OceanBase 环境跑起来了。备赛阶段所有 SQL 练习和压测都基于这个环境做。

这块还牵扯到连接池配置。OceanBase 兼容 MySQL 协议,很多驱动默认会把它识别成 MySQL,于是就会出现couldn't 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 到 4,DATE_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 --config=configs/baseline.conf \ --output=logs/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_SIZE='10G';

但某些版本对资源单元的修改有在线限制,最稳的做法还是回到第一步把环境建对,别中途反复折腾。

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.md

README 里写清楚环境怎么起、数据怎么灌、哪个配置对应哪次改动。scripts 里放压测脚本和数据生成脚本,logs 里按时间命名存放每次压测的原始输出。

验证方法我也固定下来:每次改动后跑三轮压测取中位数;对比只看 p95,不看平均值;结果表里固定记录 QPS、尾延迟、CPU 三个数字。这样每次调参是否有效,一眼就能判断。

比赛结束前,把整套东西跑一遍复现命令:

bash scripts/setup.sh && bash scripts/bench.sh

如果这条命令能在一个全新环境里完整跑通,你的备赛成果才是扎实的。名次是评审给的,但这套可复现的能力是你自己的。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询