news 2026/11/2 22:07:48

ProxySQL 仓库开发指南:构建体系、Feature Tier、TAP 测试与双协议架构详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ProxySQL 仓库开发指南:构建体系、Feature Tier、TAP 测试与双协议架构详解
  • 后端
  • 数据库
  • 负载均衡

【免费下载链接】proxysql

High-performance proxy for MySQL and PostgreSQL

项目地址:https://gitcode.com/gh_mirrors/pr/proxysql
点击查看免费下载

ProxySQL 是一个用 C++17 编写的高性能、协议感知的 MySQL / PostgreSQL 代理,提供连接池、查询路由、缓存与监控能力,基于 GPL 协议开源。本文以仓库根目录的 CLAUDE.md 为骨架,结合源码、Makefile 与测试基础设施,系统讲解本仓库的构建管线、Feature Tier 编译模型、TAP 测试流程、双协议架构与编码规范,帮助开发者和 AI 编码代理快速、正确地在本仓库中完成构建、测试与代码提交。

构建系统总览:deps → lib → src 三段式管线

ProxySQL 的构建系统基于 GNU Make,采用经典的三段式流水线,全部通过根目录的 Makefile 驱动:

deps/ → 构建 25+ 个 vendored 第三方依赖,产物为静态库 lib/ → 编译 lib/ 下约 128 个 .cpp 文件,产出 lib/libproxysql.a src/main.cpp → 链接 libproxysql.a,生成最终 proxysql 可执行文件
  • 根 Makefile 负责编排三段,并向下传递编译参数(OPTZ、PROXYSQL*系列特性开关等);
  • deps/中的依赖均以源码形式 vendored,例如jemalloc、sqlite3、mariadb-client-library、postgresql、libev、re2、libinjection、lz4/zstd、prometheus-cpp、libscram等;
  • src/main.cpp 是程序入口,负责守护进程初始化与线程启动(CLAUDE.md 中标注约 95K 行,当前实际 3513 行——注意文档数据偏旧,以仓库现状为准)。

常用构建命令(取自 CLAUDE.md 并补充说明):

# 完整 release 构建(自动根据 nproc/hw.ncpu 检测 -j) make # Debug 构建(-O0、-ggdb、-DDEBUG) make debug # 带 ASAN 的构建(必须 NOJEMALLOC=1,因为 jemalloc 与 ASAN 不兼容) NOJEMALLOC=1 WITHASAN=1 make build_deps_debug && make debug && make build_tap_test_debug # 构建 TAP 测试二进制(前提:先构建出 proxysql 可执行文件) make build_tap_tests # release 版测试 make build_tap_test_debug # debug 版测试 # 清理 make clean # 清理 src/lib 的目标文件与 libproxysql.a make cleanall # 全量清理,包括 deps 下的第三方依赖 # 构建发行包(rpm/deb/tar 等,见 Makefile 中 amd64-packages/arm64-packages 目标) make packages

注意 Makefile 中build_tap_tests/build_tap_test_debug均依赖build_src/build_src_debug,即测试二进制必须在 proxysql 二进制构建成功之后才能编译。

Feature Tier:同一份代码编译出三种产品形态

本仓库最具辨识度的构建机制是Feature Tier(特性层级):通过编译期特性开关,同一份代码库产出三种产品形态。每个 Tier 都继承更低一层的全部特性。

Tier开关标志对应版本追加特性
Stable(默认,不传标志)v3.0.x核心代理(连接池、路由、缓存、监控)
InnovativePROXYSQL31=1v3.1.xFFTO、TSDB
Plugin ChassisPROXYSQL40=1v4.0.x插件加载器 + ABI(4 阶段生命周期、query-hook、共享 Prometheus),并构建打包全部 v4.0 插件,含 mysqlx 与 genai/MCP

标志蕴含关系(源码级证据见根 Makefile):

PROXYSQL40=1 ⇒ PROXYSQL31=1 ⇒ PROXYSQLFFTO=1 + PROXYSQLTSDB=1 + PROXYSQLED25519=1

Makefile 中的ifeq链自动完成上述蕴含展开:设置PROXYSQL40=1会同时开启PROXYSQL31;设置PROXYSQL31=1会同时开启 FFTO、TSDB 与 ED25519。

关键澄清(与很多新贡献者的直觉相反):

  • 没有独立的PROXYSQLGENAI标志。所有 AI / MCP / RAG / LLM 功能都位于 plugins/genai/,通过PROXYSQL40=1统一构建与打包,运行时以.so插件形式通过dlopen加载;
  • 默认的裸make编译的是Stable Tier,明确不含 FFTO 与 TSDB(MySQLFFTO.cpp/PgSQLFFTO.cpp被排除,#ifdef PROXYSQLFFTO保护的符号如mysql_thread___ffto_max_buffer_size不会定义);
  • 因此 CI 从不构建裸默认版本:每个 CI 包构建/测试构建都会设置 Tier 标志(PROXYSQL31=1或PROXYSQL40=1),这在 .github/workflows/CI-*.yml 中有大量实例,例如PROXYSQL31=1 make -j$(sysctl -n hw.ncpu)(macOS v31 构建)与PROXYSQL40=1 make ${{ env.MAKE_TARGET }}(AlmaLinux genai 包构建)。

切换 Tier 必须 clean:stale-object tier mismatch

Makefile 不会在两次调用之间追踪 Tier 标志。在某 Tier 下编译出的目标文件与lib/libproxysql.a,会在下一次不同 Tier(或他人构建过的目录树)下被静默复用。经典症状是链接失败:

undefined reference to `mysql_thread___ffto_max_buffer_size' undefined reference to `pgsql_thread___ffto_max_buffer_size'

这不是真实损坏,也不是默认构建的 bug——它是陈旧的Tier 不匹配(例如启用了 FFTO 的libproxysql.a链接了未带PROXYSQLFFTO编译的main.o)。不要试图通过去掉 Tier 标志来“修复”。

正确做法(CLAUDE.md 原文强调)是:切换 Tier 时先清理,并且在一个会话中对每次 make 都传递同一个Tier 标志:

# 切换 Tier(或不确定目录树上次用什么 Tier 构建):先 clean make clean # 清除 lib/ + src/ 目标文件与 libproxysql.a PROXYSQL31=1 make -j$(nproc) # 然后统一用想要的 Tier 构建 # 如果 deps 也是在别的 Tier 下构建的,还需要:make cleanall(会重建 deps,较慢)

构建标志速查

  • NOJEMALLOC=1— 禁用 jemalloc 内存分配器;
  • WITHASAN=1— 启用 AddressSanitizer(要求NOJEMALLOC=1);
  • WITHGCOV=1— 启用代码覆盖率采集;
  • PROXYSQLCLICKHOUSE=1— 当前构建中默认启用(根 Makefile 在 deps/lib/src 各阶段均显式传入)。

架构:MySQL 与 PostgreSQL 的双协议并行设计

ProxySQL 的核心架构特点是双协议并行:MySQL 与 PostgreSQL 使用同一套架构设计、但各自协议专属的实现类,形成镜像的类层级:

架构层MySQL 实现PostgreSQL 实现
协议MySQL_ProtocolPgSQL_Protocol
会话MySQL_SessionPgSQL_Session
线程MySQL_ThreadPgSQL_Thread
HostGroupsMySQL_HostGroups_ManagerPgSQL_HostGroups_Manager
监控MySQL_MonitorPgSQL_Monitor
查询处理器MySQL_Query_ProcessorPgSQL_Query_Processor
日志MySQL_LoggerPgSQL_Logger

上述类均有对应的 include/ 头文件与 lib/ 实现文件,例如MySQL_Session.h/MySQL_Session.cpp与PgSQL_Session.h/PgSQL_Session.cpp,读者可直接对照阅读。

核心组件

  • Admin 接口(lib/ProxySQL_Admin.cpp、lib/Admin_Handler.cpp)——基于 SQLite3 的 SQL 式配置管理,支持无需重启的运行期配置变更;配置库 schema 版本在 include/ProxySQL_Admin_Tables_Definitions.h 中追踪。
  • HostGroups Manager——按 hostgroup 分配路由连接,支持 master-slave、Galera、Group Replication 与 Aurora 拓扑。
  • Query Processor——解析查询、匹配路由规则,通过Query_Cache处理查询缓存。
  • Monitor——对后端做健康检查,监测复制延迟、read-only 状态与连通性。
  • 线程模型——基于 libev 的事件驱动 I/O;Base_Thread为基类,协议专属的线程管理器派生其上。
  • HTTP/REST(ProxySQL_HTTP_Server、ProxySQL_RESTAPI_Server)——提供指标与管控端点。

条件编译组件

  • FFTO(Fast Forward Traffic Observer)——lib/MySQLFFTO.cpp / lib/PgSQLFFTO.cpp;
  • TSDB——时序指标与内嵌 Dashboard;
  • ClickHouse——原生 ClickHouse 协议支持;
  • GenAI / MCP / RAG / LLM——自插件拆分(carve-out)完成后全部位于 plugins/genai/,不属于libproxysql.a与proxysql二进制本体。其加载路径可通过源码确认:src/main.cpp 使用dlopen加载插件;src/proxysql.cfg 中的genai_variables=用于相关配置;注释明确指出 GenAI 的变量初始化、handler 构造与 shutdown 均已移交至 genai 插件的 init/start 回调(见 src/main.cpp 相关注释)。

测试:TAP 协议 + Docker 后端基础设施

测试采用 TAP(Test Anything Protocol)协议,运行在 Docker 化的后端基础设施之上。测试代码位于 test/tap/,基础设施脚本位于 test/infra/。

铁律:不要手动搭建 Docker 环境

永远使用run-tests-isolated.bash,它统一负责基础设施搭建、ProxySQL 启动、测试执行与清理。绝不要手动创建 Docker 网络、启动容器或运行 init 脚本——runner 会全部代劳。

被测试的 proxysql 二进制必须是 DEBUG 构建。隔离测试 harness(proxysql-tester.py)会下发 debug-only 的 admin 命令(LOAD DEBUG FROM DISK、admin-debug变量,两者均为#ifdef DEBUG保护),release 二进制会报Unknown global variable: 'admin-debug'或near "LOAD": syntax error而无法(重新)配置。这一点在 test/infra/README.md 中有同步印证。

标准流程:

# 1) 先构建 DEBUG 版二进制,并保持 Tier 标志一致 PROXYSQL31=1 make debug # 2) 搭建基础设施(后端 + ProxySQL 容器) WORKSPACE=$(pwd) INFRA_ID=dev-$USER TAP_GROUP=mysql84-g1 test/infra/control/ensure-infras.bash # 3) 运行一个 TAP group 的全部测试 WORKSPACE=$(pwd) INFRA_ID=dev-$USER TAP_GROUP=mysql84-g1 test/infra/control/run-tests-isolated.bash # 4) 运行组内单个测试 —— 用 TEST_PY_TAP_INCL 正则过滤器 # 不要为隔离单个测试而临时建组;测试仍属于其真实分组,只是做过滤 # (详见 test/infra/SKILL.md 与 test/infra/README.md) WORKSPACE=$(pwd) INFRA_ID=dev-$USER TAP_GROUP=legacy-g4 \ TEST_PY_TAP_INCL="pgsql-reg_test_5866_result_format-t" \ test/infra/control/run-tests-isolated.bash # 5) 在不拆除后端的情况下换入重建的二进制: # ProxySQL 容器运行的是工作区构建的二进制,重建后需重新执行此脚本 # (它只重建 ProxySQL 容器,保留后端;普通 ensure-infras.bash 不会拾取 # 已运行 ProxySQL 的重建二进制,docker restart 也不是受支持的机制) WORKSPACE=$(pwd) INFRA_ID=dev-$USER TAP_GROUP=mysql84-g1 test/infra/control/start-proxysql-isolated.bash

可用的 TAP group 定义在 test/tap/groups/groups.json,组名遵循<infra>-g<N>模式(如mysql84-g1、legacy-g2、pgsql16-g1、unit-tests-g1等)。TEST_PY_TAP_INCL是与组内测试名匹配的正则——这是文档规定的运行单个测试的方式。从 groups.json 可以看到,测试条目可携带版本门控注解(如"@proxysql_min_version:4.0"),同一测试可同时挂到多个组。

DO NOT 清单

  • 不要手动创建 Docker 网络(docker network create);
  • 不要手动启动容器(docker start、docker run);
  • 不要直接运行docker-compose-init.bash——请用ensure-infras.bash;
  • 不要在 worktree 之间符号链接构建产物——每个 worktree 单独构建;
  • 不要在 worktree 或仓库之间复制源文件;
  • 不要直接cd test/tap/tests && make并期望无基础设施也能通过。

测试文件约定

测试文件位于 test/tap/tests/,命名遵循test_*.cpp或*-t.cpp模式。测试二进制通过 test/tap/tests/Makefile 中的模式规则构建:make <testname>-t会把<testname>-t.cpp编译成<testname>-t。新增测试无需改 Makefile——只要添加.cpp文件并在groups.json中注册即可。

CI/测试失败的处理纪律

项目的测试质量要求极高,永远不要把 CI 失败当作"pre-existing"或"flaky"来打发——这些词是观察而非分析,把它们当结论会让真实 bug 存活下来。当分支或 PR 上的 CI 失败时:

  1. 阅读真实失败:打开失败的测试日志、其产生的 proxysql 服务日志与测试源码,定位具体的断言、超时、崩溃或非零退出,并在报告中引用相关行。
  2. 陈述根因而非症状:"Test X failed" 是症状;根因是为什么——竞态条件、陈旧 fixture、资源泄漏、协议回归、环境不匹配等。
  3. 拆成两个独立问题并分别用证据回答:
    • 本次改动是否导致该失败?——通过逐 commit 推理与代码路径分析回答,而不是只对比基线的通过/失败率;
    • 该测试是否与本次改动无关地本身就是坏的?——这是独立问题,早于本改动就存在的失败仍是要修复或登记的问题,而不是"带病合并"的理由。
  4. 若本次会话内无法确定根因,明确说出来并给出下一步调查建议(带日志重跑、插桩测试、登记跟踪 issue),不要用"flaky"掩盖不确定性。
  5. 反复失败的测试是更高优先级的 bug,而不是更低优先级的——复现本身就是失败模式可复现的证据,这正是它能被修复的原因。

单元测试 harness

单元测试位于 test/tap/tests/unit/,通过自定义 harness 链接libproxysql.a。测试必须使用test_globals.h与test_init.h(完整模式见 doc/agents/project-conventions.md,其中明确要求#include "test_globals.h"与#include "test_init.h")。从单元测试文件即可看到大量直接面向内部类的用例,例如auth_unit-t.cpp、connection_pool_unit-t.cpp、backend_sync_unit-t.cpp、caching_sha2_rsa_unit-t.cpp、duckdb_config_unit-t.cpp等。

关键依赖一览

deps/下 vendored 的第三方依赖及其用途(见 CLAUDE.md 与 deps/Makefile):

  • jemalloc— 内存分配器(可用NOJEMALLOC=1关闭,ASAN 构建必须关闭);
  • sqlite3— admin 配置存储;
  • mariadb-client-library— MySQL 协议;
  • postgresql— PostgreSQL 协议;
  • re2、pcre2— 正则引擎;
  • libev— 事件循环;
  • libinjection— SQL 注入检测;
  • lz4、zstd— 压缩;
  • curl、libmicrohttpd、libhttpserver— HTTP;
  • prometheus-cpp— 指标;
  • libscram— SCRAM 认证。

代码布局

  • include/ — 全部头文件(.h/.hpp),头文件保护采用#ifndef __CLASS_*_H风格;
  • lib/ — 核心库源码(约 128 个 .cpp,通常一文件一类);
  • src/main.cpp — 程序入口、守护进程初始化、线程启动;
  • test/tap/ — TAP 测试框架与用例;
  • test/infra/ — 基于 Docker 的测试环境;
  • .github/workflows/ — CI/CD 流水线(selftests、TAP 测试、包构建、CodeQL),架构总览见 doc/GH-Actions/README.md(ProxySQL 使用双分支 caller/reusable 拆分:CI-*.yml在v3.0,ci-*.yml在GH-Actions分支,该文档是权威参考)。

Agent 协作指南与编码规范

仓库为 AI 编码代理准备了专门文档(doc/agents/):

  • doc/agents/project-conventions.md — ProxySQL 专属规则(目录、构建、测试 harness、git 工作流);
  • doc/agents/task-assignment-template.md — 可分配给 AI agent 的 issue 编写模板;
  • doc/agents/common-mistakes.md — 已知的 agent 失败模式及预防/检测方法。

编码约定

  • 类名:PascalCase并带协议前缀(MySQL_、PgSQL_、ProxySQL_);
  • 成员变量:snake_case;
  • 常量/宏:UPPER_SNAKE_CASE;
  • 必须 C++17;条件编译使用#ifdef PROXYSQL31、#ifdef PROXYSQL40、#ifdef PROXYSQLFFTO、#ifdef PROXYSQLTSDB、#ifdef PROXYSQLCLICKHOUSE;
  • PROXYSQLGENAI已不再守卫任何核心代码(GenAI 插件拆分完成后,它只存在于 plugins/genai/ 内部);
  • 性能关键代码:注意对热路径的影响;
  • 资源管理使用 RAII;内存分配使用 jemalloc;
  • 同步使用 pthread mutex;计数器使用std::atomic<>。

总结:给开发者的最小正确工作流

把以上要点浓缩成一个可复制的起步流程:

# 1) 选好目标 Tier,并保持一致 PROXYSQL31=1 make -j$(nproc) # 日常开发推荐 v3.1(或 PROXYSQL40=1 用于 genai 插件) # 2) 切换 Tier 时务必先 clean make clean PROXYSQL40=1 make -j$(nproc) # 3) 跑 TAP 测试(debug 二进制 + 隔离 runner) PROXYSQL31=1 make debug make build_tap_test_debug WORKSPACE=$(pwd) INFRA_ID=dev-$USER TAP_GROUP=mysql84-g1 \ test/infra/control/run-tests-isolated.bash

遵循"同一 Tier 贯穿构建会话 + 切换即 clean + 始终用隔离 runner 跑测试 + 以根因分析对待 CI 失败"这几条纪律,即可避免本仓库绝大多数构建与测试陷阱。更详细的规则请随时回查 CLAUDE.md、doc/agents/project-conventions.md 与 test/infra/SKILL.md。

  • 后端
  • 数据库
  • 负载均衡

【免费下载链接】proxysql

High-performance proxy for MySQL and PostgreSQL

项目地址:https://gitcode.com/gh_mirrors/pr/proxysql
点击查看免费下载

相关推荐

上一篇:基于 Vercel 仓库 Jekyll 示例:从 Front Matter 到静态站点构建的完整实战解析
下一篇:Ovine:用JSON构建企业级管理系统的利器

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 1:51:48

2026-2027年微信小程序毕业设计选题大全:150个高通过率选题推荐✅

毕业设计选题非常重要&#xff01;非常重要&#xff01;非常重要&#xff01;&#xff08;一定要收藏起来&#xff09; &#xff0c;这篇文章分享给大家关于微信小程序毕业设计如何进行选题&#xff0c;对毕设开发需要帮助&#xff0c;以及对开题或者选题不清楚的同学都可以问学…

作者头像 李华
网站建设 2026/10/20 1:51:49

STM32+FPGA双核架构设计与实战:从通信选型到联调排错

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华