言库:数据库核心协议
使用稳定的配置、驱动、参数化 SQL、结果、事务、连接池、诊断与言据交换边界。
言库(包名 言库,仓库 yanxu-db)是言序数据库生态的稳定核心。它统一配置、驱动发现、连接、查询结果、预编译语句、事务、连接池、观测与言据交换,但不在核心包里实现 PostgreSQL、MySQL、SQLite 线协议,也不是 ORM。
| 项目 | 1.0 稳定边界 |
|---|---|
| 当前版本 | 1.0.0 |
| 最低言序 | 1.1.11 |
| 清单格式 | 2 |
| 稳定依赖 | 言据 v1.2.0、言录 v1.0.0、言时 v1.0.0 |
| 运行方式 | 纯言序;树解释器与字节码 VM 均可使用 |
| 许可 | MIT |
安装并固定公开标签
使用言包安装兼容的 1.x:
yanbao add db --package 言库 --version "^1.0"需要可复现来源时,在应用清单中同时固定公开附注标签和兼容版本范围:
[依赖]
言库 = { git = "https://github.com/yanxulang/yanxu-db.git", 修订 = "v1.0.0", 版 = "^1.0" }修改清单后应重新生成并提交格式 2 锁文件;发布和 CI 应验证离线锁,不要依赖可变的默认分支。
核心对象与驱动选择
| 对象 | 责任 |
|---|---|
数据库配置 | 保存驱动、地址、主机、端口、数据库、用户、TLS 与选项 |
驱动注册表 / 数据库 | 显式注册驱动并按配置建立连接,不使用隐式全局状态 |
驱动能力 | 报告事务、保存点、原生结构、路径查询、取消等真实能力 |
连接协议 / 预编译协议 | 参数化执行、查询、预编译、事务与生命周期 |
查询结果 / 数据库行 | 行、列元数据、影响行数、最后插入号与稳定列访问 |
事务协议 | 手动、托管、保存点、隔离、只读、超时与提交后钩子 |
连接池 | 有界等待、健康检查、空闲/寿命淘汰和优雅关闭 |
生产应用通常直接使用具体驱动的 打开配置。需要依赖注入或同时管理多个驱动时,可使用注册表:
引「包:言库」为 言库;
定 注册表 为 言库.驱动注册表()
.注册(言库.PostgreSQL驱动(执行器工厂));
定 配置 为 言库.数据库配置(「postgresql」)
.主机(「db.internal」)
.端口(5432)
.数据库(「app」)
.用户(「service」)
.TLS(「验证完整」)
.应用名(「api」);
定 连接 为 言库.数据库(注册表).连接(配置);这里的 执行器工厂 必须由真实驱动提供。应用不应自行拼装认证、TLS 或数据库线协议;测试替身可以使用 函数连接。
当前稳定驱动是:言舟(SQLite)、言库·象城(PostgreSQL)和言库·海豚(MySQL/MariaDB)。上层代码应先检查 连接.能力().支持(名称),不要假定三个后端行为相同。
参数化 SQL 与标识符
SQL 模板和值参数始终分开:
定 模板 为 言库.SQL模板(
「SELECT id, name FROM users WHERE status = $1 AND age >= $2」
);
定 结果 为 连接.查询模板(模板,【「active」,18】);
定 首行 为 结果.首行对象();
言 首行.取(「name」);| 方言 | 值占位符 | 标识引用 |
|---|---|---|
| SQLite | ? | "name" |
| PostgreSQL | $1、$2 | "name" |
| MySQL/MariaDB | %s | `name` |
参数只能代表值,不能代表表名、列名、schema、排序方向或操作符。动态标识符必须先经过业务白名单,再交给所选驱动的 方言().引名(名称),或对应的 言库.PostgreSQL方言() 等方言对象;引用只解决 SQL 语法转义,不能代替对象授权。
确实需要执行厂商管理语句时,使用带用途说明的显式边界:
连接.执行原始(言库.原始SQL(「VACUUM」,「维护窗口空间整理」));原始SQL 不会自动变安全。正文只能来自受审计源码,不得包含请求文字、密码、令牌或个人数据。
预编译、结果与资源生命周期
定 语句 为 连接.预编译模板(
言库.SQL模板(「SELECT id FROM users WHERE email = $1」)
);
定 已绑定 为 语句.绑定(【「user@example.test」】);
定 结果 为 已绑定.查询();
言 结果.全部();
言 结果.列元数据();
言 结果.影响行数;
言 结果.末插入号;
语句.关闭();全部() 保留驱动行表示;需要稳定列名和列序号访问时使用 行对象()、首行对象()与 列元数据()。重复列名、缺列或列表行宽度不一致会返回明确错误,不会静默覆盖。
预编译绑定会复制参数。语句关闭后,原语句和已有绑定都拒绝执行;具体原生驱动的语句也不能跨连接或在池租约释放后继续使用。
事务与保存点
托管事务在回调成功时提交,抛错时回滚:
法 更新账户(事务) 则
定 账户 为 事务.查询(查询SQL,【42】).首行对象();
事务.执行(更新SQL,【账户.取(「id」)】);
事务.提交后(提交后通知);
归 账户;
终
定 账户 为 连接.托管事务(
更新账户,
言库.事务选项()
.隔离(「可串行化」)
.只读(假)
.超时(3000)
.标识(「account-42」)
);嵌套工作必须从当前事务调用 保存点() 或 事务(),并按后进先出结束。只读事务拒绝写入与言据导入。提交后钩子只在最外层提交完成后运行;钩子失败不代表数据库提交已回滚。
测试可用 事务选项().完成后回滚(真):回调结果正常返回,但数据库变化回滚且不执行提交后钩子。手动事务则必须在每条控制路径明确 提交() 或 回滚()。
连接池
定 池配置 为 言库.连接池配置()
.最小(2)
.最大(20)
.取得超时(2000)
.空闲超时(300000)
.最大生命周期(1800000)
.健康间隔(30000)
.等待上限(100)
.关闭超时(10000);
定 池 为 言库.连接池(新连接,池配置);
定 租约 为 池.取得();
试 则
言 租约.查询(「SELECT 1」,【】).标量();
租约.释放();
救 所误 则
租约.释放();
抛 所误;
终
池.关闭平缓(10000);租约必须在所有路径释放。池会剔除关闭、健康失败、空闲超时或寿命到期的连接,并补足最小连接数。有等待额度时池执行有界等待;队列满、取得超时和优雅关闭超时分别返回稳定错误。池不会自动重放可能已经提交的写操作。
测试可以注入言时虚拟时钟或使用 虚拟连接池,无需真实等待。
反射与迁移边界
言库没有伪造一个“所有数据库都相同”的反射或迁移 API。厂商目录、锁和 DDL 事务语义由驱动实现:
| 后端 | 反射入口 | 迁移边界 |
|---|---|---|
| SQLite / 言舟 | 表清单()、表结构()、列/索引/外键信息 | BEGIN IMMEDIATE 写锁内校验并原子登记 |
| PostgreSQL / 象城 | schema/表清单、表结构(模式, 名称) | advisory transaction lock,DDL 与登记位于事务内 |
| MySQL/MariaDB / 海豚 | 数据库/表清单、表结构(模式, 名称) | GET_LOCK 命名锁;DDL 隐式提交,不承诺整体回滚 |
应用可直接使用驱动的版本化迁移器。需要模型反射、开发期安全加法计划、SQL/代码/言据动作迁移和种子时,使用言映。无论选择哪一层,生产流程都应先检查、干运行、备份并在精确数据库版本演练。
超时、取消、日志与指标
定 令牌 为 言库.取消令牌();
定 选项 为 言库.执行选项()
.超时(500)
.取消令牌(令牌)
.请求标识(「query-1」);
定 结果 为 连接.查询带选项(SQL,参数,选项);同步核心只能在驱动调用前后检查令牌与截止时间,不能强制抢占任意同步执行器。只有驱动明确声明 查询取消 并安装原生取消器后,连接.取消(请求标识) 才能取消正在执行的数据库请求。
言录适配默认只记录驱动、动作、SQL 模板、参数数量与类型、耗时、影响行数、请求/事务标识、慢查询和错误代码,不记录参数值。数据库配置.转安全典() 用于诊断脱敏;建立真实连接必须使用保留凭据的 转驱动配置()。
言据:规范文本与原生结构
这两种策略不能混用:
| 策略 | 数据库列 | 写入内容 | 适用场景 |
|---|---|---|---|
规范文本 | TEXT/CLOB | 可严格复原的规范 .yj 文本 | 跨数据库交换、逐字稳定存储 |
原生结构 | PostgreSQL JSONB、MySQL JSON、SQLite JSON1 文本 | 言序普通值,由驱动映射 | 数据库路径查询和原生索引 |
定 文本 为 言库.言据写入值(资料,「规范文本」,连接.能力());
定 还原 为 言库.言据读取值(文本,「规范文本」);普通 JSON 文本不是规范言据文本。选择 原生结构 前必须通过驱动能力门禁,读回时也必须按同一策略恢复言序值。
查询结果可导出为带 yanxu-db/rows 格式标识的规范言据信封,并严格参数化导入:
定 正文 为 连接.导出言据(
言库.言据导出配置(「SELECT id, profile FROM users」).最大行(10000)
);
定 摘要 为 连接.导入言据(
正文,
言库.言据导入配置(「archive.users」).批量(100).要求规范(真)
);默认导入使用单一事务并严格检查列。核心不申请文件权限;读写 .yj 文件、对象存储或流,应通过 导出言据到 / 导入言据自 注入由应用授权的回调。
权限与安全责任
言库 1.0.0 自身固定为零权限:
[权限]
文件 = []
网络 = []
TCP监听 = []
UDP绑定 = []
环境 = []
进程 = false
原生扩展 = false具体驱动与顶层应用负责网络或文件目标、TLS、凭据和原生扩展权限。言库不验证驱动客户端的密码学或内存安全,也不提供身份认证、行级授权、备份或数据库审计存储。
兼容性与明确限制
- 1.x 保持公开类型、法名、配置键、结果信封、错误代码和默认安全边界;新增可选能力属于兼容变化。
- 单条 SQL 最多 1 MiB,参数最多 65,536 个;注册驱动最多 64 个。
- 言据交换最多 100,000 行、1,024 列和 16 MiB 正文;单批导入最多 1,000 行。
- 连接池最多 10,000 个连接、100,000 个等待者;提交后钩子最多 128 个。
- 通用层不保证查询抢占、自动重试、厂商迁移、schema 反射或数据库 JSON 与言据文本等价;这些能力必须由具体驱动明确实现并报告。
- SQLite、PostgreSQL 与 MySQL/MariaDB 的
RETURNING、数组、JSON、DDL 事务和取消语义不同,跨库代码必须按能力分支并在目标数据库版本上集成测试。
错误以 YANKU_ 稳定代码分类。仓库与 1.0.0 Release:yanxulang/yanxu-db。