大家好,我是 iamkz。
在 OpenTenBase 分布式环境中,插件开发完成以后,还需要经历编译、文件分发、数据库注册、功能验证和回滚等环节。
对于 SQL-only 插件,需要将 .control 和 SQL 安装脚本部署到 OpenTenBase 的 extension 目录。
对于 C 插件,还要使用目标 OpenTenBase 的开发环境完成编译,生成 .so 共享库,再将 .control、SQL 和 .so 分发到相关服务器。
当集群中存在多个 CN、DN 和多台服务器时,手工完成这些操作会遇到很多实际问题:
- 插件文件应该发送到哪些服务器;
.control、SQL 和.so应分别进入什么目录;- C 插件应该使用哪一个
pg_config编译; - 编译产物是否完整;
- 远端文件是否与本地文件一致;
- 数据库注册前是否已经能够发现 extension;
- 应该在哪个 CN 上执行注册;
- 注册完成后插件能否在多个 CN 上正常调用;
- 回滚时应该清理哪些数据库对象。

为了解决这些问题,我开发了 plugin_ctl。
项目地址:
https://github.com/iamkuangzhang/opentenbase-plugin_ctl
那么接下来,我将使用一个 C 语言编写的 hello_world 插件,演示 plugin_ctl 如何完成项目创建、集群初始化、状态检查、编译、部署、注册、验证和回滚。
一、plugin_ctl 解决什么问题?
plugin_ctl 是一个面向 OpenTenBase 的插件生命周期管理工具。
在设计过程中,我们学习了 opentenbase_ctl 和 pgxc_ctl 的管理风格,将插件相关操作集中到一个交互式控制台中。
它可以创建 SQL-only 或 C 插件项目,识别 OpenTenBase 集群,检查插件文件,编译 C 共享库,将安装文件分发到 CN、DN 所在服务器,在数据库中注册 extension,并执行功能验证和数据库对象回滚。
对于已经存在的插件源码,也可以将其加入管理,再继续完成检查、编译、部署和注册。
在执行过程中,plugin_ctl 会根据本地文件、远端文件和数据库状态判断插件当前所处的阶段。当编译产物、部署文件或数据库条件不满足时,会阻止后续操作并给出对应提示。

二、测试环境与下载方式
本文使用的 OpenTenBase 测试环境如下:
OpenTenBase 版本:
OpenTenBase_v5.21.8.11
服务器:
192.168.244.130
192.168.244.132
GTM:
192.168.244.130:6666
CN:
192.168.244.130:30004
192.168.244.132:30005
DN:
192.168.244.130:20008
192.168.244.132:20009
OpenTenBase 安装目录为:
/data/opentenbase/install/opentenbase_bin_v2.0
本文使用的 Python 路径为:
/opt/python3.11/bin/python3.11
其他环境需要根据实际安装位置调整相关路径。
下载 plugin_ctl
plugin_ctl 已在 GitHub 开源,本文通过源码方式运行。
先使用 root 用户下载项目:
cd /opt
git clone https://github.com/iamkuangzhang/opentenbase-plugin_ctl.git \
opentenbase-pluginctl
将项目目录交给 opentenbase 用户:
chown -R opentenbase:opentenbase /opt/opentenbase-pluginctl
创建全局启动命令:
cat >/usr/local/bin/plugin_ctl <<'EOF'
#!/usr/bin/env bash
export PYTHONPATH=/opt/opentenbase-pluginctl/src${PYTHONPATH:+:$PYTHONPATH}
exec /opt/python3.11/bin/python3.11 -m plugin_ctl "$@"
EOF
chmod +x /usr/local/bin/plugin_ctl
切换到 OpenTenBase 运行用户:
su - opentenbase
查看版本:
plugin_ctl --version
当前正式版本输出为:
plugin_ctl 1.0.0

三、使用 init 初始化集群配置
开始管理插件之前,需要先让 plugin_ctl 识别当前 OpenTenBase 集群。
进入 OpenTenBase 工作目录:
cd /data/opentenbase
启动 plugin_ctl 交互式控制台:
plugin_ctl
进入控制台后执行:
pluginctl> init

初始化完成后,会生成:
~/.plugin_ctl/cluster.toml

这份配置记录了后续插件管理需要使用的集群信息,包括:
- 当前使用的集群管理后端;
- CN 和 DN 的节点名称;
- 节点所在服务器;
- 数据库连接端口;
- extension 目录;
- 共享库目录;
- 数据库连接信息。
cluster.toml 不直接保存 pg_config 路径。执行 build 时,plugin_ctl 会根据其中的 extension_dir、lib_dir 等目录信息推导当前 OpenTenBase 对应的 pg_config。
在本文环境中,plugin_ctl 使用 opentenbase_ctl 作为集群操作后端。
初始化时,plugin_ctl 会先获取集群中的初步节点信息,再连接可用 CN 查询数据库中的 pgxc_node,校验节点名称、角色、IP 和端口。

对应的数据库拓扑可以通过下面的 SQL 查看:
SELECT node_name,
node_type,
node_host,
node_port
FROM pgxc_node
ORDER BY node_name;
本文环境最终识别到:
2 个 CN
2 个 DN
对应端口为:
CN:30004、30005
DN:20008、20009
除了 opentenbase_ctl,plugin_ctl 也保留了对 pgxc_ctl 环境的兼容能力。
后续的 C 插件编译、文件分发、远程校验和数据库注册,都会使用 cluster.toml 中的配置。
四、进入控制台并查看 help
执行:
plugin_ctl
进入交互式控制台:
pluginctl>
查看当前支持的命令:
pluginctl> help

帮助信息中会列出插件创建、查看、检查、编译、部署、注册和回滚等命令。
切换中文和英文
plugin_ctl 控制台默认使用英文。
输入CH ,可以切换为中文;

这时候,帮助信息、操作提示、错误信息和确认信息都会显示为中文。
输入EN ,可以切换为英文。

同时支持小写形式(ch,en)
命令名称、插件 ID、节点名称、文件路径以及状态值不会随着语言切换而改变。
五、使用 new 创建插件项目
new 用于创建一个新的插件项目,并自动将该插件加入 plugin_ctl 管理目录。
创建 SQL-only 插件
下面两种写法作用相同,选择其中一种即可:
pluginctl> new hello
或者显式指定 SQL-only 类型:
pluginctl> new -sql hello

不要在同一目录下连续执行这两条命令创建同名插件,否则第二次会因为目录已经存在而失败。
生成的目录结构如下:
hello/
├── README.md
├── manifest.yml
├── hello.control
├── sql/
│ ├── hello--0.1.0.sql
│ ├── verify.sql
│ └── rollback.sql
└── .pluginctlignore

SQL-only 插件不包含 C 源码和 .so 共享库,因此不需要执行编译。
完成 SQL 安装脚本后,可以直接进入检查和部署阶段。
创建 C 插件
执行:
pluginctl> new -c hello_world

生成的目录结构如下:
hello_world/
├── README.md
├── manifest.yml
├── Makefile
├── hello_world.control
├── src/
│ └── hello_world.c
├── sql/
│ ├── hello_world--0.1.0.sql
│ ├── verify.sql
│ └── rollback.sql
└── .pluginctlignore

其中:
src/hello_world.c保存 C 源码;Makefile使用 PGXS 完成编译;hello_world.control描述 extension;hello_world--0.1.0.sql定义数据库函数;verify.sql用于验证插件;rollback.sql用于回滚数据库对象;manifest.yml描述插件类型、文件列表和构建方式。
new 创建完成后,插件会自动进入 plugin_ctl 管理目录,不需要再次执行 add。
六、在生成的框架上开发 hello_world
本文使用:
pluginctl> new -c hello_world
创建 C 插件项目框架。
随后在生成的框架中完成 C 函数、安装 SQL、验证脚本和回滚脚本。
完成后的插件提供:
SELECT hello();
预期返回:
hello_world
C 插件源码的具体编写过程不是本文重点,这里不再展开。
关于 hello_world 扩展的基本开发过程,可以参考:
腾讯云开发者平台:
https://cloud.tencent.com/developer/article/2691122
CSDN:
https://blog.csdn.net/2501_90201337/article/details/162047784?spm=1001.2014.3001.5501
接下来主要演示 plugin_ctl 如何管理已经完成开发的 C 插件。
七、使用 list 查看插件
执行:
pluginctl> list

可以查看当前由 plugin_ctl 管理的插件。
查看指定插件的详细信息:
pluginctl> list hello_world
由于 hello_world 是通过 new 创建的,因此已经自动加入管理目录。
check、build、deploy 和 register 都通过插件 ID 查找项目,所以执行这些操作前,插件必须能够在 list 中找到。
对于已有的插件源码目录,可以通过下面的命令加入管理:
pluginctl> add ./hello_world
八、第一次 check:确认当前状态
执行:
pluginctl> check hello_world
此时 C 源码、Makefile、control 文件和 SQL 脚本已经存在,但还没有生成:
hello_world.so
因此插件状态为:
BUILD_REQUIRED
该状态表示 C 插件已经具备源码和构建配置,下一步需要先完成编译。
如果源码、Makefile、manifest 或其他关键文件存在错误,才会进入相应的异常状态。

九、使用 build 编译 C 插件
执行:
pluginctl> build hello_world

build 会读取 manifest.yml,并完成以下操作:
- 判断插件类型;
- 检查 C 源码;
- 检查 Makefile;
- 定位
pg_config; - 检查 PGXS;
- 执行清理和编译;
- 检查
.so是否生成。
本文环境使用的 pg_config 为:
/data/opentenbase/install/opentenbase_bin_v2.0/bin/pg_config
对应版本为:
PostgreSQL 11.0 @ OpenTenBase_v5.21.8.11
实际编译过程相当于:
make clean
make \
PG_CONFIG=/data/opentenbase/install/opentenbase_bin_v2.0/bin/pg_config
编译成功后,插件目录中会生成:
hello_world.so
build 只负责生成编译产物,不会执行:
make install
插件文件的安装和多机分发继续由 deploy 统一完成。
编译结束后再次执行:
pluginctl> check hello_world
此时状态应变为:
READY

十、使用 deploy 分发插件文件
执行:
pluginctl> deploy hello_world
正式复制前,plugin_ctl 会展示部署计划。
C 插件需要部署三类文件:
hello_world.control
→ extension 目录
hello_world--0.1.0.sql
→ extension 目录
hello_world.so
→ library 目录
.control 和安装 SQL 会进入 OpenTenBase 的 extension 目录。
.so 会进入 pg_config --pkglibdir 对应的共享库目录。
目标服务器根据 CN 和 DN 的部署位置确定。
本文环境包含 2 个 CN、2 个 DN,分别位于两台服务器上。

确认部署计划后,控制台会询问是否继续:
Continue? [y/N]: y
随后,plugin_ctl 会完成文件分发,并检查:
- 远端文件是否存在;
- SHA-256 是否与本地一致;
- 所有目标是否同步成功。



部署完成后,立即执行:
pluginctl> check hello_world
文件分发和校验全部通过时,状态变为:
DEPLOYED

同时,数据库应当能够在 pg_available_extensions 中看到 hello_world。
十一、使用 register 注册插件并完成功能验证
执行:
pluginctl> register hello_world
注册前,plugin_ctl 会检查:
- primary CN 是否可以连接;
pg_available_extensions中是否存在该扩展;pg_extension中是否已经注册。
确认注册计划后,控制台会询问是否继续:
Continue? [y/N]: y
检查通过后,在 primary CN 执行:
CREATE EXTENSION IF NOT EXISTS hello_world;
注册完成后,plugin_ctl 会检查多个 CN 中 pg_extension 记录的版本是否一致。


随后执行:
pluginctl> check hello_world
状态应变为:
REGISTERED

register 负责完成 extension 注册,不会自动运行插件的 verify.sql。功能验证需要继续执行:
pluginctl> verify hello_world
验证成功时会返回:
OK

还可以分别连接两个 CN,执行:
SELECT hello();
预期返回:
hello
-------------
hello_world

真实测试中,该函数在两个 CN 上均能正常调用。
十二、使用 rollback 回滚数据库对象
需要回滚时执行:
pluginctl> rollback hello_world
控制台会先展示回滚计划,并询问是否继续:
Continue? [y/N]: y


确认后,plugin_ctl 会读取 manifest 中配置的回滚脚本,并删除数据库中的 extension 和相关对象。
可以使用下面的 SQL 检查:
SELECT count(*)
FROM pg_extension
WHERE extname = 'hello_world';
回滚后结果应为:
0
rollback 不会删除已经分发到服务器上的:
hello_world.control
hello_world--0.1.0.sql
hello_world.so
数据库对象和物理文件分别处理,可以避免自动删除仍可能被其他数据库使用的共享文件。
十三、使用 remove 取消管理
数据库对象回滚完成后,可以执行:
pluginctl> remove hello_world
remove 会将插件从 plugin_ctl 管理目录中移除。

它不会再次执行数据库回滚,也不会删除远端 .control、SQL 和 .so 文件。
因此推荐先执行:
rollback hello_world
再执行:
remove hello_world
如需删除服务器上的物理文件,应先确认没有其他数据库或插件版本继续使用,再单独进行清理。
可以重新管理该插件:
pluginctl> add ./hello_world
十四、使用 plugin_ctl 时需要注意什么?
1. init 会根据现有集群管理工具识别环境
plugin_ctl 不会替代 opentenbase_ctl 或 pgxc_ctl。
执行 init 时,它会根据当前环境选择可用的集群管理后端,获取 CN、DN、服务器和安装目录等信息,再结合数据库中的 pgxc_node 校验集群拓扑,最终生成 cluster.toml。
当前环境使用 opentenbase_ctl 时,plugin_ctl 会优先通过它识别集群;存量环境仍使用 pgxc_ctl 时,也可以通过对应的兼容方式完成初始化。
2. init 应在正式管理插件前执行
首次使用时,应先在控制台执行:
pluginctl> init
该命令会生成 ~/.plugin_ctl/cluster.toml。后续的编译、部署和注册都会使用其中的节点、目录和数据库连接信息。
3. build 只针对已经管理的插件
执行 build 前,插件必须能够通过下面的命令找到:
pluginctl> list
通过 new 创建的插件会自动加入管理。已有源码项目需要先执行:
pluginctl> add ./hello_world
4. SQL-only 插件不需要 build
SQL-only 插件不包含 C 源码和 .so,文件完整后可以直接检查和部署。
只有 C 插件需要执行:
pluginctl> build hello_world
5. C 插件应使用目标 OpenTenBase 的 pg_config
C 插件编译时,应使用当前 OpenTenBase 安装目录中的 pg_config,例如:
/data/opentenbase/install/opentenbase_bin_v2.0/bin/pg_config
使用其他 PostgreSQL 版本的 pg_config,可能造成头文件、PGXS 或库目录不一致。
6. build 不会执行 make install
build 只生成 .so 编译产物,不会将文件直接安装到数据库目录。
插件文件的安装和多机分发统一由 deploy 完成。
7. rollback 不会删除物理文件
rollback 只清理数据库中的 extension 和相关对象。
已经部署到服务器上的 .control、SQL 和 .so 文件仍然保留。
8. remove 不等于卸载 extension
remove 只取消 plugin_ctl 对插件的管理,不会执行数据库回滚。
推荐顺序是:
pluginctl> rollback hello_world
pluginctl> remove hello_world
9. 可以使用上下方向键浏览历史命令
交互式控制台支持使用上下方向键查看以前输入过的命令。
历史记录保存在:
~/.plugin_ctl/history
退出并重新进入控制台后,历史命令仍然保留。
10. 中英文切换只在当前会话生效
输入:
CH
切换中文,输入:
EN
切回英文。
重新进入控制台后,默认仍然使用英文。命令名称、插件 ID、文件路径和状态值不会被翻译。
总结
plugin_ctl 是一个面向 OpenTenBase 分布式环境的插件生命周期管理工具。
它将插件项目创建、集群识别、状态检查、C 代码编译、文件分发、数据库注册、功能验证和对象回滚集中到同一个交互式控制台中,为 SQL-only 插件和 C 插件提供统一的管理入口。
在没有 plugin_ctl 时,C 插件的处理过程通常需要手工查找 pg_config、执行 PGXS 编译、确认 .so 产物、复制 extension 文件和共享库,再连接数据库执行 CREATE EXTENSION。在多机集群中,还需要逐台确认 CN、DN 所在服务器的文件是否完整。
plugin_ctl 将这些分散操作组织成一条可以检查状态、预览计划、执行操作和验证结果的流程。
对于 SQL-only 插件,可以在完成项目文件后直接检查、部署和注册;对于 C 插件,则可以通过 build 使用目标 OpenTenBase 的开发环境生成共享库,再继续完成多机部署和数据库注册。
这套方式减少了手工复制和重复操作,也让每个阶段的状态更加清晰。当源码尚未编译、远端文件缺失或者数据库注册条件不满足时,plugin_ctl 会在进入下一步之前给出提示,避免问题继续扩散到整个集群。
通过本文的 hello_world 示例,plugin_ctl 1.0.0 已经在真实双机 OpenTenBase 集群中完成了 C 插件创建、PGXS 编译、文件分发、extension 注册、双 CN 调用和数据库对象回滚。
从源码到数据库可用,OpenTenBase 插件所需要经历的关键步骤,现在可以通过一套统一、可检查、可验证的流程完成。


1169

被折叠的 条评论
为什么被折叠?



