.veb 文件。当您运行 INSTALL EXTENSION 时,VillageSQL 会加载您的库,调用您的注册代码,并立即将您的函数作为 SQL 函数提供——可以从任何查询中调用,就像它们是内置在服务器中的一样。无需重新启动服务器。本页的其余部分解释了该过程的每个步骤是如何工作的。
术语
- VEB(VillageSQL 扩展包)-
.veb文件格式,一个包含清单、库和元数据的 tar 归档文件 - VEF(VillageSQL 扩展框架)- 用于编写扩展的 C++ 和 Rust SDK
- VDF(VillageSQL 定义函数)- 通过 VEF 注册的函数——在 C++ 中通过
VEF_GENERATE_ENTRY_POINTS(),或在 Rust 中通过extension!宏
VDF 函数查找
VDF 支持限定和非限定函数调用:- 系统函数(内置 MySQL)
- UDF(传统 MySQL 用户定义函数,通过
CREATE FUNCTION ... SONAME) - VDF(扩展函数)- 仅当存在具有该名称的唯一函数时
- 存储函数(使用
CREATE FUNCTION创建)
extension_name.function_name())。
**性能:**对于热代码路径,使用限定调用(extension_name.function_name())以跳过解析链并直接调用扩展函数。
VEB 文件格式
VillageSQL 扩展以.veb(VillageSQL 扩展包)文件的形式分发——包含以下内容的 tar 归档文件:
manifest.json 架构
- **name:**必须与 SQL 中使用的扩展名称匹配(小写字母加下划线)
- **version:**语义版本(MAJOR.MINOR.PATCH)
- **description、author、license:**可选元数据
扩展生命周期
安装流程
.so 文件将被卸载。
**符号隔离:**扩展使用 RTLD_LOCAL 标志加载,确保一个扩展中的符号不会与另一个扩展中的符号冲突。这可以防止多个扩展使用通用库名称或函数名称时发生命名冲突。
系统变量
veb_dir 指向存储 .veb 扩展文件的目录。卸载流程
扩展目录结构
VillageSQL 将.veb 文件解包到 MySQL 数据目录中,以支持多个版本:
- 测试新版本,而不会覆盖旧版本
- 启用回滚
- 防止“相同版本,不同代码”
Victionary 缓存层
VictionaryClient 维护系统元数据的内存缓存,以实现 O(log n) 查找。缓存操作
**缓存失效:**在 DDL 操作期间自动进行(INSTALL/UNINSTALL EXTENSION)。
**内存开销:**每个条目约为 100 字节。
自定义类型系统
类型解析
实现类型
自定义类型映射到 MySQL 存储类型:并发性和事务行为
线程安全模型
扩展函数以每行执行模型调用:- **隔离的每行执行:**每个函数调用都有自己的结果缓冲区(设计上是线程安全的)
- **预运行/后运行钩子:**语句级设置/清理,每个 SQL 语句调用一次
- **不保证隔离:**多个连接可以并发调用您的函数
- **最佳实践:**避免全局状态;使用函数参数和返回值
事务行为
扩展函数应遵循以下最佳实践:- 尽可能设计函数为无状态的
- 避免在函数中使用持久性副作用(文件写入、外部 API 调用)
- 如果使用预运行/后运行状态,请适当处理清理
性能注意事项
**优化:**使用预运行钩子来缓存昂贵的每语句设置,而不是对每一行重复执行。自定义类型性能
安全性和调试
安全模型
**信任模型:**扩展以完整的服务器权限运行。- 没有沙盒或权限系统
- 扩展可以读取任何文件、访问网络、执行代码
- **信任影响:**仅从受信任的来源安装扩展
villagesql_extension_installer 用户运行(上下文切换)。
调试扩展
调试扩展
启用详细日志:GDB 调试:检查依赖关系:常见错误:
- **未定义的符号:**使用
ldd(Linux)或otool -L(macOS)检查库依赖关系 - **无法打开共享对象:**检查库依赖关系是否存在且正确链接
- **VDF 调用时崩溃:**检查 NULL 指针处理
后续步骤
创建扩展
构建您的第一个扩展
系统参考
系统表和视图
示例
研究 vsql_complex 实现
管理扩展
监控和故障排除

