整理代码
This commit is contained in:
1 parent
e87c4ee6a8
commit
a45e33f94b
39 files changed
+264
-917
No files matched your search
+34
-116
@@ -1,16 +1,22 @@
|
||||
# 架构与组件
|
||||
|
||||
[← 返回 README](../README.md)
|
||||
|
||||
**本页导航:** [组件与访问路径](#组件与访问路径) · [数据目录](#数据目录) · [会话与并发](#会话与并发) · [SQL 查询处理](#sql-查询处理) · [快照事务](#快照事务) · [WAL 与崩溃恢复](#wal-与崩溃恢复) · [页面与空间回收](#页面与空间回收) · [身份、授权与系统目录](#身份授权与系统目录) · [权限变更与会话失效](#权限变更与会话失效) · [扩展方向](#扩展方向)
|
||||
|
||||
ChuSQL 采用客户端 / 服务端架构。正常运行时,只有数据库服务直接访问数据文件;离线初始化与恢复由 bootstrap 完成。
|
||||
|
||||
## 组件与访问路径
|
||||
|
||||
~~~text
|
||||
Web / CLI / 其他客户端
|
||||
↓ TCP
|
||||
chusql-server
|
||||
↓
|
||||
SQL 引擎 → Rust 存储层 → 磁盘
|
||||
~~~
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CLI[CLI / 其他客户端] -->|TCP| Server[chusql-server]
|
||||
Browser[浏览器] -->|HTTP| Web[chusql-web]
|
||||
Web -->|TCP| Server
|
||||
Server --> Engine[Haskell SQL 引擎]
|
||||
Engine --> Storage[Rust 存储层]
|
||||
Storage --> Disk[(磁盘)]
|
||||
```
|
||||
|
||||
| 组件 | 职责 |
|
||||
| --- | --- |
|
||||
@@ -21,11 +27,13 @@ Web / CLI / 其他客户端
|
||||
| chusql-core/storage | catalog、页面、B+ 树、缓存、WAL 与持久化 |
|
||||
| csql-bootstrap | 安装引导及离线系统目录修复、恢复、重置 |
|
||||
|
||||
查询 AST 的 `Select` 使用 `selectItems :: [(String, Expr)]` 保存输出名称与投影表达式;普通列使用 `Col`,别名、计算和聚合使用相同结构。便捷函数 `makeSelect` 接受列名列表并构造这些投影项。
|
||||
|
||||
服务默认监听 127.0.0.1:7777,Web 默认监听 127.0.0.1:7778。配置位置和平台数据目录见 [config.md](config.md)。
|
||||
|
||||
## 数据目录
|
||||
|
||||
[storage] data_dir 是持久化数据的根目录,诊断日志由 log_files 单独指定。
|
||||
`[storage] data_dir` 保存持久化数据,`log_files` 单独指定诊断日志目录。
|
||||
|
||||
| 位置 | 内容 |
|
||||
| --- | --- |
|
||||
@@ -47,6 +55,8 @@ Web / CLI / 其他客户端
|
||||
|
||||
查询依次经过解析、基于 schema 的语义检查、优化和执行。库名、表名、列名及别名在语义层解析;存储层使用精确的表名键。
|
||||
|
||||
绑定查询保存依赖对象编号、schema 版本、列定义和传递 DOMAIN 依赖。执行前复查,真实存储的每次读取还在相关库读锁内验证全部依赖;结构改变或对象替换明确报错。守卫不提供整条多请求查询的数据快照;旧目录的未知身份/版本保留兼容校验,旧存储未确认守卫则拒绝执行。
|
||||
|
||||
| 能力 | 实现与边界 |
|
||||
| --- | --- |
|
||||
| 派生表 | 内层独立解析,必须有别名,不能引用外层列;输出列按别名暴露 |
|
||||
@@ -115,120 +125,28 @@ Web / CLI / 其他客户端
|
||||
|
||||
TCP 连接在下一次请求时返回 unauthorized 并关闭;空闲连接不被强行中断。权限逐条查询,避免继续使用旧授权。Web 会话还通过账号版本校验,口令或身份变更使旧凭据失效。
|
||||
|
||||
## 查询引擎扩展设计(尚未实现)
|
||||
## 扩展方向
|
||||
|
||||
按 bound IR → 子查询物化 / 递归 CTE 推进;DOMAIN 约束见[类型文档](types.md#domain-约束设计尚未实现)。以下设计尚未实施,当前能力见前文;实施状态以 .agents/context/progress.txt 为准。
|
||||
> [!NOTE]
|
||||
> 以下是规划,不能作为当前 SQL、事务或恢复能力使用。进度与验收见 `.agents/context/progress.txt`。
|
||||
|
||||
### bound IR
|
||||
|
||||
#### 列与作用域绑定
|
||||
已有列槽位、类型化函数与 `BoundQuery`;后续补齐多级词法作用域、来源/列身份,以及写语句与约束的统一绑定。迁移保留同名遮蔽、NULL / DOMAIN、输出布局和错误时序,结构改写应在绑定前完成或重新绑定。
|
||||
|
||||
保留语法 AST 用于解析和诊断;语义检查产出独立 `BoundStatement`,规划、优化及执行逐步只接收它。列引用绑定为作用域编号、来源编号、列编号和类型,保留原始位置用于诊断;相关列明确标记所属外层作用域,不再通过字符串补限定名辨认身份。
|
||||
### 查询扩展
|
||||
|
||||
#### 表达式类型与错误语义
|
||||
| 方向 | 前置条件与边界 |
|
||||
| --- | --- |
|
||||
| 通用子查询物化 | 缓存绑定对象/schema、外层值及快照,保留惰性求值和首次错误;限制内存、执行预算及取消 |
|
||||
| 递归 CTE | 先实现类型一致的迭代关系,明确去重、循环终止、轮次与行数预算;不隐含支持写入型 CTE |
|
||||
|
||||
表达式节点携带结果类型、nullable、已解析运算符/函数标识和显式转换。没有证据证明安全时 `may_error` 为 true;优化不得删除或提前求值可能报错的表达式。未定型 NULL 只参与推导,最后绑定到上下文类型;不允许流入存储 schema。DOMAIN 身份保留在类型节点中,比较可以用底层语义,赋值需经过领域校验。
|
||||
### 存储扩展
|
||||
|
||||
#### schema 与对象版本
|
||||
| 方向 | 前置条件与边界 |
|
||||
| --- | --- |
|
||||
| 行版本 MVCC | 稳定且不复用的 `row_id`、版本链与快照序号;提交复查写冲突和唯一键,旧索引候选随活跃快照保留 |
|
||||
| 跨页 compact | MVCC 与稳定定位映射,影子文件经 WAL 原子切换;保留旧读引用和逻辑扫描顺序 |
|
||||
| 并行写 | 固定对象/行/唯一键锁序及取消机制,WAL/CSN 发布保持连续已应用前缀;DDL、权限和目录变更继续排序 |
|
||||
|
||||
绑定仅使用 schema,不能扫描数据或打开索引。catalog 解析对象后提供 schema 与版本;执行前再次验证稳定对象编号和 schema 版本。统计独立附着,不纳入绑定身份。内存存储使用与磁盘相同的绑定规则。
|
||||
|
||||
#### 实施与验收
|
||||
|
||||
迁移顺序为查询表达式 → RelOp 输入 → 写语句和约束;过渡适配器单向转换且仅位于边界,不维护两套优化规则。验收用现有查询全集并补同名遮蔽、相关列、别名、NULL/DOMAIN 和错误时序回归;既有可观察顺序保持。
|
||||
|
||||
### 通用子查询物化
|
||||
|
||||
#### 惰性执行与缓存身份
|
||||
|
||||
引入查询内 `LazyMaterialize` 算子:首次实际需要时执行,保留结果行序与重复;非相关查询每语句一次,相关查询按 bound IR 外层列绑定值缓存。缓存键沿用规范值相等、NULL 与领域底层语义,并绑定子计划和执行视图;不能跨语句、会话或权限版本复用。
|
||||
|
||||
#### 求值语义
|
||||
|
||||
首版只物化已证明确定且无副作用的子计划;可能报错的表达式保持现有首次使用和短路路径,无法证明错误时序相同的改写禁用。空输入不触发子查询,标量多行仍在实际消费时报错。ANY/ALL、IN、EXISTS 各自保留三值及空集规则,不能用集合去重替代结果。
|
||||
|
||||
#### 预算与回退
|
||||
|
||||
预算同时限制单缓存、查询总缓存和相关键数量;超过预算时在执行该次子计划前选择不缓存的原路径,不能重跑已执行一半的计划。磁盘溢写作为后续阶段,需明确临时目录、类型编码、权限及取消清理。EXPLAIN 展示物化范围与估算,运行统计不泄露缓存行值。
|
||||
|
||||
#### 验收条件
|
||||
|
||||
验收比较启用/禁用的结果多重集、行序、首次错误、空输入、NULL、重复外层绑定、多次 CTE 引用、预算及取消;不确定函数不可复用。
|
||||
|
||||
### 递归 CTE
|
||||
|
||||
#### 首版语法范围
|
||||
|
||||
保留现有非递归 WITH 行为;新增 WITH RECURSIVE 走绑定作用域,不在解析期无限展开。首版仅单一自引用、锚点 UNION ALL 递归项;自引用只能出现在递归项 FROM,锚点不可引用自身。互递归、多个自引用、递归项聚合/排序/LIMIT、外连接及非单调子查询明确拒绝。UNION 去重递归留后续设计,不能冒用 UNION ALL。
|
||||
|
||||
#### 类型绑定与迭代
|
||||
|
||||
锚点和递归项输出列数相同;显式列名唯一,先由锚点确定类型,再校验递归项可赋值转换,不按运行数据扩宽。无法给锚点 NULL 定型时要求显式类型。执行用 worktable,递归项仅读取上一轮 delta,按轮次和每轮既有行序追加输出,保留 UNION ALL 重复。
|
||||
|
||||
#### 资源预算与终止
|
||||
|
||||
拟定默认深度 1000、累计行数 100000、内存 64 MiB,并受服务端上限限制;达到任一预算返回 resource_limit,不返回截断结果。深度定义为递归项执行轮数;delta 为空正常终止。外层 LIMIT 首版不作为终止证明,先完整执行递归再消费,避免隐藏循环/错误。取消释放所有 worktable。
|
||||
|
||||
#### 验收条件
|
||||
|
||||
验收覆盖零轮、多轮、重复路径、循环超限、NULL/类型冲突、空锚点、名称遮蔽、非法自引用和查询取消。EXPLAIN 明确递归与预算。
|
||||
|
||||
## 存储与事务扩展设计(尚未实现)
|
||||
|
||||
先引入稳定行编号和 MVCC,再实施跨页 compact 与并行写。前置条件是新页格式、版本化 WAL、离线升级工具及恢复验收。
|
||||
|
||||
新格式必须标版本,旧二进制拒绝打开。旧数据在保留备份的停服副本上升级、校验后发布,不混用新旧写入路径。每阶段先运行改动模块的规定测试入口,全量门禁由所有者运行;性能数据不能代替语义、恢复或权限验收。
|
||||
|
||||
### 行版本 MVCC
|
||||
|
||||
#### 身份与可见性
|
||||
|
||||
引入库内单调 row_id,独立于用户 `id`、主键及物理槽号;删除不复用。每版本包含 row_id、版本编号、创建/结束提交序号与前版本定位,未提交版本只在事务私有工作集内。读视图固定 snapshot_csn,选取创建序号不大于快照且结束序号大于快照的版本,再合并自身修改。提交序号与 WAL LSN 分离,映射随提交记录持久化。
|
||||
|
||||
每连接仍只允许一个事务,保持快照隔离和保存点语义;不声称可串行化,写偏斜仍可能发生。写集记录读取的基线版本,提交验证该版本仍为最新;同 row_id 更新/删除冲突返回 serialization_failure。唯一键冲突在当前已提交状态和本次写集联合检查,不能仅用开始快照验证。无业务 id 的表也按 row_id 提交,不再整表替换。
|
||||
|
||||
索引键定位 row_id,索引查询再按快照检查版本;更新键保留旧键候选直到所有活跃快照不再需要,不能只索引最新值。扫描先保持旧格式导入的行序,更新不改 row_id 的扫描位置,新插入按持久化序号排序;不得借 MVCC 无意改变现有无 ORDER BY 输出。
|
||||
|
||||
#### 提交、恢复与回收
|
||||
|
||||
首版仍串行提交:验证 → 分配 CSN → WAL 记录版本变化及提交 → fsync → 应用 → 统一发布可见 CSN。读者仅获取已完整应用的可见序号;持久化提交后应用失败继续采用 recovery_required 封闭请求,不能把已提交组当作失败撤销。不引入未提交脏页,因此首版保持 redo-only;若将来允许提前刷未提交页,必须另行设计 undo/状态恢复。
|
||||
|
||||
保存点记录私有写集边界与不可变根,回退不撤销其他事务版本。活跃快照登记器包括流式扫描和物化消费者;最老快照决定旧版本回收界线。回收同时处理 heap 和索引,读定位有 pin,取消/断线可靠注销。长事务受现有寿命及新增保留空间预算限制,不能为了回收静默推进其快照。
|
||||
|
||||
升级在停服副本中为旧行分配 row_id、初始版本和顺序,重建索引,验证行数/值/约束后切换;不得把重复业务 id 合并。新 WAL 与页格式显式版本化,截断仍遵循已刷盘检查点,不顺带改成页 LSN 检查点。
|
||||
|
||||
#### 验收条件
|
||||
|
||||
验收包含重复/缺失业务 id、旧快照与键更新、删除重插、保存点、唯一并发冲突、写偏斜边界、长读回收、断线及提交每个持久化边界的崩溃恢复;复测 BEGIN/COMMIT 的传输和比较成本。
|
||||
|
||||
### 跨页 compact
|
||||
|
||||
#### 定位与影子页
|
||||
|
||||
使用 row_id 到版本位置的存储内部定位映射,索引不保存可失效的页/槽定位。首版在表维护独占锁下进行,等待该表读 pin 释放;其他表仍可运行。以快照回收界线保留所有可能可见版本,按既有逻辑扫描顺序打包到影子页和定位映射,随后 WAL 记录并原子切换文件代次。
|
||||
|
||||
#### 恢复与旧版本保护
|
||||
|
||||
旧代次直到无读引用且新代次检查点完成才删除;提交前崩溃丢弃影子文件,提交后重放切换。映射缺失、重复 row_id/版本和校验失败明确报错,不返回缺行扫描。隐藏列一并按当前 schema 改写,旧快照需要的结构不得提前删除。跨页整理不改变对象编号、行编号、值或输出顺序。
|
||||
|
||||
#### 验收条件
|
||||
|
||||
验收验证前后全量扫描和索引点/范围查一致、快照旧版本、隐藏列、页损坏、空间不足、取消与文件切换崩溃;记录回收页数及 IO,不能只比较耗时。
|
||||
|
||||
### 并行写
|
||||
|
||||
#### 实施顺序与锁范围
|
||||
|
||||
先允许事务私有写集准备并行,继续保留短串行 WAL/CSN 发布;第二阶段按稳定表编号与 row_id 排序取得写锁、唯一键锁。DDL/维护使用库结构锁,跨表事务必须一次取得完整锁集,禁止边执行边任意升级。权限读门在执行和最终复查期间保持现有语义;目录及 ACL 修改仍单独排序。
|
||||
|
||||
#### 唯一键锁与取消
|
||||
|
||||
唯一键锁使用与值相等一致的规范编码,缺主键也使用 row_id 锁。等待有取消与超时,超时返回明确错误且保持/回退事务遵循现有错误分类;固定锁序避免内部锁环,不承诺支持任意用户锁或死锁自动重试。
|
||||
|
||||
#### 提交发布顺序
|
||||
|
||||
允许不同表/行的验证和页面准备并行,但同一页短 latch、catalog 高水位、索引节点和 WAL 写入仍保护。发布 CSN 必须按提交顺序形成连续已应用前缀,后提交不能跨过未完成组而对读者可见。group commit 为后续性能阶段,不能改变每组原子性和持久化失败语义。
|
||||
|
||||
#### 验收条件
|
||||
|
||||
验收覆盖同表不同行、同一行、唯一键冲突、跨表相反顺序、DDL/compact/撤权竞争、超时取消和 WAL 故障;用确定同步点断言并发结果,再单独测吞吐与等待时间。
|
||||
新页格式、版本化 WAL、离线升级和恢复验证是前提。升级在停服副本上保留备份并校验后发布;旧二进制不得打开不支持的格式。任何持久化应用失败须保持 `recovery_required`,不将已提交 WAL 组当作失败撤销。性能收益不能代替语义、权限和崩溃恢复验证。
|
||||
Reference in new issue
Block a user