Author: xinkang/zhonghu
数据库是企业数据的基石,而内核稳定性则是这块基石的地基。地基不稳,上层建筑再华丽也经不起风雨。本文将介绍阿里云 PolarDB PostgreSQL 版(下文简称 PolarDB-PG)研发团队如何从零构建一套研发自测系统,在日常开发过程中持续发现并修复内核缺陷,将产品故障率降低了一个数量级。
数据库不同于普通应用软件——它承载着用户最核心的数据资产。一个微小的内核 Bug,可能导致数据丢失、索引不一致、主备切换失败,甚至引发大规模线上故障。对于数据库而言,测试不是锦上添花,而是生死攸关。
然而,原有的测试流程面临几个现实挑战:
随着 PolarDB-PG 支持的版本越来越多、功能越来越丰富,对稳定性的要求也越来越高。团队深刻认识到:仅靠发版前的集中测试远远不够,必须在日常开发过程中就持续发现问题。 于是,内核研发团队决定投入力量,构建一套研发人员自己日常使用的测试系统——作为原有测试流程的有力补充,在代码合入的第一时间就开始”体检”。
在动手之前,团队广泛调研了业界的测试实践:
这些思路各有所长,但没有一个能完全满足 PolarDB-PG 内核团队的需求。团队决定取各家之长,结合自身特点,构建一套量身定制的测试体系。
全员共建,而非单点依赖
由少数研发同学率先搭建起框架骨架,提供开发手册,其他研发同学根据自己开发的新功能,自行添加测试用例。功能的开发者最了解自己的代码应该如何测试,这种模式既降低了测试开发的门槛,又确保了测试用例的针对性。
聚焦内核,有所取舍
数据库的测试范围可以无限大,但资源总是有限的。团队做了清晰的取舍:
极致自动化,解放生产力
研发人员天生喜欢用工具解决重复性工作。从调度、执行、错误检测、缺陷创建到指派通知,全链路自动化是这套系统的灵魂。
整个研发自测系统围绕以下五大核心能力构建:
┌─────────────────────────────────────────────────────────┐
│ 自动化调度引擎 │
│ 7×24h 不间断运行,上万种配置自动轮转 │
├──────────┬──────────┬──────────┬──────────┬──────────────┤
│ 多种工作 │ 云服务 │ 自动化 │ 数据化 │ 多架构 │
│ 负载并发 │ 模拟测试 │ 缺陷管理 │ 运营体系 │ 适配 │
│ 压测引擎 │ 引擎 │ 引擎 │ │ │
└──────────┴──────────┴──────────┴──────────┴──────────────┘
│ │ │ │
┌────┴────┐ ┌────┴────┐ ┌───┴───┐ ┌───┴────┐
│ 容器化 │ │ 资源池 │ │ 元数据 │ │ 监控 │
│ 测试环境 │ │ 管理 │ │ 中心 │ │ 报表 │
└─────────┘ └─────────┘ └───────┘ └────────┘
传统测试通常是”一种负载跑一遍”,而真实的生产环境中,用户的业务远比这复杂。研发自测系统的核心思路是:让测试负载比真实业务复杂若干倍,如果数据库在极端高压下能稳定运行,那么在用户场景下只会更稳定。
系统同时运行多种类型的工作负载,它们相互并发、相互干扰,模拟最极端的场景:
所有这些负载同时运行,而不是依次执行。这种”暴力美学”的测试方式,能够暴露出许多在单一负载下永远不会触发的并发问题。
测试用例的设计也有讲究:
search_path 来实现同一份 SQL 在不同表类型(普通表、分区表、临时表、全局临时表等)下的复用数据库在云上运行,除了常规的增删改查,还会频繁经历各种运维操作:主备切换、节点扩缩容、规格变配、版本升级等。这些操作期间的内核稳定性至关重要。
系统模拟了多种云服务场景,包括:
每种模拟都遵循统一的三阶段模式:
模拟前(Pre-check) → 执行模拟(Simulate) → 模拟后(Post-check)
├─ 实例状态检查 ├─ 执行具体操作 ├─ 事务状态校验
├─ 校验数据准备 ├─ 等待操作完成 ├─ 数据页正确性校验
└─ 位点延迟准备 └─ 验证预期结果 └─ 一致性校验
关键设计: 所有服务模拟都与 SQL 压测同时进行。这意味着在数据库承受高并发读写压力的同时,还要经历主备切换、节点增减等操作——这比真实生产环境更加极端。
发现问题只是第一步,高效地将问题传递给正确的人才是关键。系统实现了从错误检测到缺陷指派的全链路自动化:
错误检测:
错误归一化与去重:
智能指派:
状态追踪:
用搭建应用程序的思路来搭建测试系统——元数据库是整个系统的神经中枢,一切皆入库:测试配置、运行记录、测试结果、缺陷信息、修复记录、资源使用情况、高可用操作历史……所有数据都有据可查,构建了完整的数据化运营体系:
PolarDB-PG 需要支持多种 CPU 架构和操作系统版本,同时在不同的测试环境中运行。系统通过面向对象的高度抽象设计,用统一的接口屏蔽了不同环境之间的差异,对每种新环境只需进行少量适配即可接入。
系统目前支持三种测试形态,各有侧重:
Docker 容器环境(主力环境)
最轻量的测试形态,也是日常大规模并发测试的主战场:
Kubernetes 云原生环境
比容器环境稍重,更接近真实的云上部署形态:
线上真实环境
最重的测试形态,以真实用户视角验证产品质量:
统一抽象的关键设计:
测试框架(统一接口调用)
│
├── Docker 环境 → 黑屏脚本执行 Shell 命令
├── K8s 环境 → K8s 命令操作
└── 线上环境 → 阿里云 OpenAPI 调用
同一套测试逻辑,只需切换底层实现,即可在三种环境中运行。这种设计使得测试能力的扩展和新环境的接入成本极低。
PolarDB-PG 的测试维度非常丰富:
| 维度 | 示例 |
|---|---|
| 数据库版本 | PG 11 / 14 / 15 / 16 / 17 / 18 |
| 兼容模式 | PostgreSQL 模式 / Oracle 模式 |
| CPU 架构 | x86 / ARM |
| 操作系统 | 多种版本 |
| 工作负载 | DML / DDL / 内置负载 / 专项负载 |
| 表类型 | 普通表 / 分区表 / 临时表 / 全局临时表等 |
| SQL 协议 | Simple / Prepared / Extended |
| 事务模式 | 无事务 / 随机事务 / 两阶段事务 |
| 并行模式 | 默认并行 / 强制并行 |
| 编译参数 | Debug / Release / 各种断言开关 |
| GUC 配置 | 默认配置 / 各种特殊参数组合 |
| … | … |
这些维度自由组合,产生了 数万种测试配置。
为了在有限的物理机上最大化测试并发度,系统实现了一套微型的资源管理系统:
研发自测系统在测试 PolarDB-PG 内核的过程中,也发现了一些 PostgreSQL 社区原生代码中的稳定性问题,并将这些问题反馈给了 PostgreSQL 全球社区,推动了社区的修复与进步。这是一个双赢的结果:PolarDB-PG 基于 PostgreSQL 内核深度定制,对内核的极限压测既保障了自身产品的稳定性,也为整个 PostgreSQL 生态做出了贡献。
自系统上线以来,研发自测系统已成为发现内核稳定性缺陷的重要渠道:
从系统上线后的几个财年来看:
系统进行了大量的高可用测试,发现并修复了若干主备切换相关的问题,直接提升了线上运维质量:
研发自测系统不是要替代原有测试流程,而是形成互补:
| 维度 | 原有测试流程 | 研发自测系统 |
|---|---|---|
| 测试阶段 | 版本发布前 | 日常开发全程 |
| 测试频率 | 版本发布前集中测试 | 7×24h 不间断 |
| 测试环境 | 接近生产环境 | 轻量容器环境 |
| 侧重点 | 功能正确性、兼容性 | 稳定性、极端场景 |
| 编译模式 | Release | Debug(更多断言检查) |
两者在测试阶段、测试环境、测试侧重点上各有不同,形成了良好的互补关系,共同守护产品质量。
PolarDB-PG 研发自测系统从最初的一个小型框架,逐步成长为覆盖数万种配置、7×24 小时不间断运行的自动化测试体系。它与专业测试团队的严格测试、阿里云对产品稳定性的一贯高标准要求,以及整个研发团队在代码质量上的持续投入,共同构成了 PolarDB-PG 稳定性保障的多道防线。
这个过程中,我们最深刻的体会是:对于数据库这样的基础软件,测试的重要性怎么强调都不为过。 每一个被测试发现的 Bug,都是一次潜在的线上故障被提前消灭。每一次主备切换的成功率提升,都意味着用户的业务少了一次中断的风险。
基础不牢,地动山摇。 而持续、自动化、极端场景下的测试,就是加固地基最有效的方式。
本文基于 PolarDB PostgreSQL 版研发团队的实践经验撰写。PolarDB 是阿里云自研的云原生关系型数据库,广泛应用于金融、政务、互联网等行业。