Files
ChuBlog/docs/architecture.md
T

58 lines
4.1 KiB
Markdown
Raw Normal View History

# 架构与组件
ChuSQL 采用客户端 / 服务端架构。数据库文件仅由 `chusql-server` 直接访问,其他组件通过网络接口与数据库服务通信。
## 主要组件
| 组件 | 作用 |
| --- | --- |
| `chusql-server` | 数据库服务,负责 SQL 执行、权限检查、事务与数据访问 |
| `chusql-web` | Web 管理端,通过数据库服务访问数据 |
| `csql` | 命令行客户端,通过数据库服务执行 SQL |
| `chusql-core/engine` | SQL 解析、语义检查、优化与执行 |
| `chusql-core/storage` | 页面、索引、日志与持久化存储 |
## 数据流
典型访问路径为:
```text
Web / CLI / 其他客户端
↓
TCP
↓
chusql-server
↓
SQL 引擎与存储层
↓
磁盘
```
所有 SQL 和权限检查均由数据库服务统一处理。Web 和 CLI 不直接访问数据目录,因此多个客户端可以同时连接同一数据库服务。
## 数据目录
数据保存在 `[storage] data_dir` 指定的位置,主要包含:
| 目录 | 内容 |
| --- | --- |
| `system/` | 系统数据库,包括账号和权限等系统信息 |
| `databases/<数据库名>/` | 用户创建的数据库 |
安装完成后只有系统数据库,不自动创建业务数据库。业务数据库需通过 `CREATE DATABASE` 创建。
## 数据库服务
`chusql-server` 默认监听 `127.0.0.1:7777`,客户端建立连接后完成登录、数据库选择和 SQL 执行。
2026-10-03 16:49:23 +08:00
每条连接拥有独立会话状态,例如当前数据库选择不会影响其他连接。不同连接可以同时执行语句:读请求之间可以并行,写请求之间由存储层排队。
语句里的库前缀和表限定符由引擎在语义层解析:存储层只接受精确的表名键,因此 `FROM sales.orders` 与选定 `sales` 后的 `FROM orders` 指向同一张表。
2026-10-03 19:12:11 +08:00
显式事务在会话层实现:`BEGIN` 把当前数据库整库读成内存快照,事务内的语句都在快照上执行;`SAVEPOINT` 把当前快照压进会话里的保存点栈,`ROLLBACK TO` 退回该点并保留它,`RELEASE` 丢掉该点与其后的保存点;`COMMIT` 先把快照、基线与库里现值按行 `id` 逐键比对,检测到写写冲突就报 `serialization_failure` 并保留事务;没有冲突才把差分用一条 `apply_transaction` 请求交给存储层应用;`ROLLBACK` 直接丢弃快照。因此隔离级别是快照读加原子提交:事务里看不到别的事务未提交或后来提交的改动,提交对外一次性可见,冲突由调用方回滚或重试。
2026-10-03 16:49:23 +08:00
2026-10-03 17:23:16 +08:00
WAL 负责崩溃恢复:每条记录带自增 LSN,一组写操作与一条提交标记一次落盘;每组提交在数据和字典都刷盘之后把 `wal.checkpoint` 推进到这条提交的 LSN,含义是「到此为止的改动都已落盘」,再按这个边界丢掉日志前缀——所以日志里通常只有当组在飞的记录。进程重启时只重放检查点之后的记录,按标记分组取已提交的组、丢弃没有标记的整组,重放前逐条做幂等检查作为第二道保险,结束后再把检查点推到最后一条提交。LSN 从检查点与文件尾里较大的那个续号,跨重启单调,`SystemStatus` 应答里的 `last_lsn` 报告该检查点 LSN。建表、删表、建索引、删索引与数据改动走同一条 WAL,恢复时一并重放。
2026-10-03 19:21:02 +08:00
系统数据库及部分管理操作仅允许管理员访问。系统表统一用 `__system_` 前缀:账号表 `__system_users` 对语句通道隐藏,角色、授权、成员三张表(`__system_roles` / `__system_grants` / `__system_members`)只在 `system` 库里可见,权限服务自身也通过 SQL 读写它们;存储启动时把旧名 `sys_roles` / `sys_grants` / `sys_members` 连同数据与索引文件一起迁移过来。角色支持互相继承:`GRANT 角色 A TO 角色 B` 记一条 B 属于 A 的成员关系,判定权限时沿成员关系算出向上闭包再取并集;写入时拒绝成环与自继承,删角色会清掉它两个方向的成员关系。
服务监听地址、端口和请求限制可在 `chusql.toml` 的 `[server]` 分区中配置。