ABI 边界
VillageSQL 扩展通过一个二进制接口 (ABI) 与服务器交互,该接口在扩展与服务器之间有着清晰的所有权分离。 服务器拥有:- 存储:InnoDB 读写字节;它不解释这些字节
- 模式:列类型元数据以及每个类型由哪个扩展注册都存储在 VillageSQL 系统表中,并在重启后持久保留
- 恢复、复制和备份:这些操作作用于原始字节,与任何内置列类型相同
- 扩展注册:名称、版本以及函数/类型注册在启动时从 VillageSQL 系统表重新加载
- 二进制格式:
from_string编码函数定义了写入磁盘的内容;to_string在输出时将其读回 - 业务规则:验证、比较、哈希和错误处理
- 状态:扩展不会在服务器为其存储的字节之外持久保留任何内容
villagesql/sdk/include/villagesql/abi/types.h。
自定义类型如何存储
当您将某列声明为UUID(以 vsql-uuid 为例)时,服务器会为每行存储一个固定长度的原始字节块。人类可读的形式——例如 d7d665f3-bb13-4c2f-b10f-d2126eb40cba——仅存在于边界处:from_string 在写入时将其编码为二进制,to_string 在读取时将其解码回来。中间的一切——存储、重做日志、崩溃恢复、二进制日志——都作用于这些字节而不解释它们。
崩溃恢复
扩展会在服务器重启时自动重新加载——无需手动干预。您可以通过INFORMATION_SCHEMA.EXTENSION_REGISTRATION 来验证这一点,它在重启后显示的注册条目与重启前相同。
行数据通过 InnoDB 的正常崩溃恢复得以存续。扩展的二进制格式从不被特殊处理——InnoDB 处理 UUID 列的方式与处理 VARBINARY 列没有任何不同。
二进制日志格式
在行格式复制(默认方式)中,自定义类型的值以原始二进制形式在二进制日志中传输。没有重新编码步骤:写入 binlog 时不会调用扩展的from_string,而 to_string 仅在客户端读回该值时才被调用。
一个 UUID 列的行级二进制日志条目如下所示:
to_string 将它们解码为可读值;而未安装该扩展的消费者——例如外部 CDC 管道或 binlog 读取器——只能看到原始字节。
还原
还原 VillageSQL 服务器的工作方式与崩溃恢复相同:服务器启动,读取其扩展注册信息,并自动加载每个扩展。对于扩展类型的列不需要特殊处理——原始字节就在备份中,扩展会按需对其进行解码。 扩展不存储在数据库内部——它们作为.veb 文件存在于磁盘上的 veb_dir 中。如果服务器在已还原的实例上启动时缺少 VEB 文件,启动会以 VEB file not found 中止。.veb_expansion_cache 不能替代 .veb 本身。在分发您的扩展时,请确保您的用户知道要将 veb_dir 与数据目录一起包含在任何备份或服务器迁移中。
模式操作
对含有扩展类型列的表执行ALTER TABLE 的行为与对内置类型完全相同。服务器在其模式元数据中跟踪该列的扩展绑定,并且该绑定在表重建后得以存续。在含有 vsql-uuid id 列的表上添加或修改其他列,会使 UUID 数据保持完好。
