言库·海豚:MySQL 与 MariaDB 驱动
连接 MySQL 8.x 与 MariaDB 10.x/11.x,使用 TLS、参数化查询、事务、连接池、反射、迁移与 JSON 言据路径。
言库·海豚(包名 言库海豚,仓库 yanxu-mysql)是言库 1.x 的 MySQL/MariaDB 原生驱动。它通过言序 ABI v2 和成熟的 Rust MySQL 协议实现直接连接数据库,提供 TLS、预编译、事务、连接池、取消、结构反射、迁移和 JSON/言据集成。
| 项目 | 1.0 稳定边界 |
|---|---|
| 当前版本 | 1.0.0 |
| 最低言序 | 1.1.12 |
| MySQL | 8.x |
| MariaDB | 10.x、11.x |
| 稳定依赖 | 言库 v1.0.0 / ^1.0 |
| 原生 ABI | v2 |
| 运行方式 | 字节码 VM、包运行或 YXB;树解释器不能载入 |
安装并固定公开标签
yanbao add mysql --package 言库海豚 --version "^1.0"可复现生产清单:
[依赖]
言库海豚 = { git = "https://github.com/yanxulang/yanxu-mysql.git", 修订 = "v1.0.0", 版 = "^1.0" }
[权限]
网络 = ["db.example:3306"]
原生扩展 = true依赖不会替顶层应用授权。若配置自定义 CA 文件,还要只对该文件授予读取权限。
建立安全连接
引「包:言库海豚」为 海豚;
定 配置:典 为 {
「主机」:「db.example」,
「端口」:3306,
「数据库」:「account」,
「用户」:「account-service」,
「密码」:安全配置【「数据库密码」】,
「TLS」:「验证完整」,
「选项」:{
「连接超时毫秒」:5000,
「读取超时毫秒」:10000,
「写入超时毫秒」:10000
}
};
定 数据库 为 海豚.打开配置(配置);也可传 mysql:// 地址,再用分离的主机、端口、数据库、用户或密码覆盖。连接建立后驱动执行 SET NAMES utf8mb4 和 SET time_zone = '+00:00'。
| TLS 模式 | 行为 |
|---|---|
验证完整 | 默认;要求 TLS,验证证书链和连接主机名 |
要求 | 与 验证完整 使用相同的完整验证 |
优先 | 仅在服务端明确不支持 TLS 时允许降级;坏证书、错误 CA 或主机名不匹配不会降级 |
禁用 | 明文;仅限隔离本机服务 |
根证书路径 可放在顶层或 选项 中。打开(...) 默认完整验证;打开本地(...) 固定 127.0.0.1 与明文,只适合受控测试。1.0 不支持客户端证书/私钥认证或跳过证书验证。
参数化查询与预编译
公共代码优先使用言库 MySQL 方言的 %s:
数据库.执行(
「CREATE TABLE users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(64) NOT NULL, profile JSON NOT NULL)」,
【】
);
定 插入 为 数据库.预编译(
「INSERT INTO users(name, profile) VALUES(%s, %s)」
);
插入.执行(【「子衿」,{「等级」:10}】);
言 插入.参数数();
插入.关闭();
定 用户 为 数据库.查询(
「SELECT id, name, profile FROM users WHERE name = %s」,
【「子衿」】
).首行();原生 ? 占位符也可使用。驱动只规范化可执行 SQL 上下文中的 %s,不会改写引号、反引号标识符或注释内文字;值随后通过服务端预编译协议绑定,不拼入 SQL。
参数不能代表表名、列名、数据库名、排序方向或操作符。动态标识符必须先经业务白名单,再使用 数据库.方言().引名(名称)。执行原始 / 查询原始 只接受受审计迁移或框架 SQL。
预编译语句和 绑定(参数) 对象都属于创建它们的物理连接。连接关闭或池租约释放后,子资源立即失效。重复结果列名会返回 MYSQL_COLUMN_DUPLICATE;联表列应使用唯一别名。
类型映射与 MariaDB JSON 边界
| MySQL/MariaDB 类型 | 言序读取值 | 1.0 写入边界 |
|---|---|---|
整数、YEAR、BIT | 数;超安全整数为文 | 整数数或数值文 |
FLOAT/DOUBLE | 数;非有限值为文 | 有限数 |
DECIMAL/NUMERIC | 保精度十进制文 | 数或十进制文 |
| 字符与文本 | 文 | UTF-8 文 |
| 二进制与 BLOB | 字节 | 字节 |
MySQL JSON | 结构化言序值 | 空、理、数、文、列、典 |
MariaDB 持久基表 JSON | 经约束确认后为结构化值 | 同上 |
| 日期时间 | 稳定 ISO 风格文 | 服务端接受的日期时间文 |
TIME | 含符号与微秒的时段文 | 服务端接受的时间文 |
TINYINT(1) 仍按整数处理,驱动不会根据显示宽度猜测布尔。MariaDB 的 JSON 是带 JSON_VALID 约束的 LONGTEXT 别名;只有结果列可追溯到持久基表且目录确认该约束时才结构化解码。临时表、视图、无源表达式或普通 BLOB 保留线路层文字/字节,即使内容看起来像 JSON,也不做启发式解析。
事务、保存点、超时与取消
引「包:言库」为 言库;
法 转账(事务)则
事务.执行(
「UPDATE accounts SET balance = balance - %s WHERE id = %s」,
【10,甲】
);
定 保存点 为 事务.保存点();
保存点.执行(
「UPDATE accounts SET balance = balance + %s WHERE id = %s」,
【10,乙】
);
保存点.提交();
归 「已提交」;
终
定 结果 为 数据库.托管事务(
转账,
言库.事务选项()
.隔离(「可重复读」)
.只读(假)
.超时(5000)
);支持的隔离名是 读未提交、读已提交、可重复读 和 串行化。回调成功提交、抛错回滚;同一连接只允许一个顶层事务,嵌套工作使用保存点。手动事务必须在所有路径结束。
MySQL/MariaDB 的许多 DDL 会隐式提交,因此“事务回滚成功”不能作为多条 DDL 整体原子的证明。
单次操作可设超时与请求标识:
定 选项 为 言库.执行选项()
.超时(2000)
.请求标识(「report-20260718」);
定 结果 为 数据库.查询带选项(SQL,参数,选项);数据库.取消(同一标识) 通过独立管理连接发送 KILL QUERY,只匹配当前活动请求。超时后主连接会重建;取消竞态无法确认时物理连接会被丢弃。取消写请求不证明服务端未提交,应用必须使用幂等键、唯一约束、事务与业务对账。
连接池
定 池配置 为 言库.连接池配置()
.最小(2)
.最大(16)
.取得超时(2000)
.空闲超时(300000)
.最大生命周期(3600000)
.健康间隔(30000)
.等待上限(64);
定 连接池 为 海豚.创建连接池(配置,池配置);
定 租约 为 连接池.取得();
言 租约.查询(「SELECT CURRENT_TIMESTAMP AS current_time」,【】).首行();
租约.释放();
连接池.关闭平缓(10000);池检查健康、空闲时间和生命周期,并剔除协议状态可疑的连接。它不会自动重放失败写请求;租约释放后不得继续使用其事务、预编译语句或绑定对象。
结构反射
逐 数据库名 于 数据库.模式清单() 则
言 数据库名;
终
定 结构 为 数据库.当前表结构(「users」);
若 结构【「存在」】 则
言 结构【「列」】;
言 结构【「约束」】;
言 结构【「索引」】;
言 结构【「外键」】;
终反射通过 information_schema 覆盖数据库、表、视图、列、主键、检查/唯一/外键约束、复合索引与外键动作。数据库名与表名作为参数传入目录查询;缺失对象返回 存在 = 假 的稳定空结构。
版本化迁移
定 各迁移 为 【
海豚.迁移(
1,
「创建用户」,
「CREATE TABLE users(id BIGINT PRIMARY KEY) ENGINE=InnoDB」,
「DROP TABLE users」
),
海豚.迁移(
2,
「增加姓名」,
「ALTER TABLE users ADD COLUMN name VARCHAR(64)」,
「ALTER TABLE users DROP COLUMN name」
)
】;
定 迁移器 为 海豚.默认迁移器(数据库);
言 迁移器.检查(各迁移);
言 迁移器.干运行升级(各迁移);
迁移器.升级(各迁移);默认登记表为 _yanxu_migrations,迁移器使用连接级 GET_LOCK 命名锁,锁内重读严格前缀历史。版本、名称和双向 SQL 进入 SHA-256;缺失定义、名称/内容漂移和不可逆回退会拒绝。
MySQL/MariaDB DDL 通常隐式提交,迁移器不声称 DDL 与登记整体原子。失败后,已成功执行并登记的前缀保留,当前失败 DDL 也可能留下结构效果;必须审计实际结构、登记与备份,再决定修复或回退。发布迁移应在 MySQL 和 MariaDB 上分别演练。旧空校验和只能在人工核对后显式采用。
言据与原生 JSON
| 策略 | 数据库列 | 语义 |
|---|---|---|
规范文本 | TEXT/LONGTEXT | 规范 .yj 文本,适合跨方言稳定交换 |
原生结构 | MySQL JSON / 经确认的 MariaDB JSON 别名 | 结构化值,适合数据库路径条件 |
定 写入值 为 数据库.言据写入值(资料,「原生结构」);
数据库.执行(「INSERT INTO profiles(data) VALUES(%s)」,【写入值】);
定 条件 为 数据库.言据路径(「data」,【「等级」】).至少(10);
定 各行 为 数据库.查询(
(「SELECT data FROM profiles WHERE 」 加 条件.SQL),
条件.参数()
).全部();路径和比较值参数化,列名由方言引用。JSON索引建议 不返回可直接执行的通用 DDL,因为生成列类型、长度和排序规则必须由业务评审;索引应写入受审计迁移。数据库 JSON 不是规范言据文本。
真实支持矩阵
数据库服务
| 产品与版本 | 支持状态 | 1.0 发布证据边界 |
|---|---|---|
| MySQL 8.0 | 支持 | 发布 CI 真实服务生命周期门禁 |
| MySQL 8.4 | 支持、最高已验证 MySQL 主版本 | 发布 CI 完整明文/TLS/错误证书/源码与 YXB;全生态实测 8.4.10 |
| MariaDB 10.x | 支持 | 10.11 进入发布 CI 真实服务生命周期门禁 |
| MariaDB 11.x | 支持、最高已验证 MariaDB 主版本 | 11.8 进入完整发布门禁;全生态实测 11.8.8 |
这里的主版本范围是驱动协议承诺。应用仍应在自己的精确补丁、SQL mode、字符集、排序规则、时区、存储引擎和集群配置上执行类型往返、迁移与故障测试。
原生目标
| 操作系统 | x86-64 | ARM64 | 发布门禁 |
|---|---|---|---|
| macOS | 支持 | 支持 | Mach-O、ABI、安装名、签名与原生消费者 |
| Linux glibc 2.17+ | 支持 | 支持 | ELF、ABI、动态依赖与原生消费者 |
| Windows | 支持 | 支持 | PE、ABI、静态 CRT 与原生消费者 |
制品路径、大小与 SHA-256 以 v1.0.0 清单为准。缺失目标应明确失败,不得回退加载其他架构制品。
权限、安全边界与明确限制
- 顶层应用需授权精确数据库网络目标和原生扩展;自定义 CA 路径还需要最小文件读取权限。
- 原生层固定拒绝
LOAD DATA LOCAL INFILE,避免服务端请求读取客户端本地文件。 - SQL 最大 1 MiB、参数最多 65,535 个;单次结果最多 100,000 行、1,024 列和 16 MiB,返回前完整解码。
- 1.0 不提供异步逐行流、自动读写分离、客户端负载均衡、客户端证书认证或自动断线重放。
- 驱动不声明 PostgreSQL 式
RETURNING、数组或只读副本路由。 - MariaDB 临时表、视图与无源表达式不能可靠识别 JSON 别名;保留文字/字节是明确安全行为。
- 默认日志不记录参数值、密码、完整 URL 或 CA 内容;自定义观测实现仍须脱敏。
厂商错误归一为 YANKU_*,海豚边界使用 MYSQL_* / YANHAITUN_* 稳定代码。仓库与 1.0.0 Release:yanxulang/yanxu-mysql。