MetonaSqlark
基于 TypeScript 的前端关系型数据库,支持完整 SQL 查询、Query Builder 链式 API、与 AriaEngine 自研存储引擎。
✨ 特性
- 🚀 AriaEngine 自研存储引擎 — LSM-Tree + SSTable 4KB 页面化物理存储(BufferPool LRU 缓存 + FileManager 页面管理,v0.5.0 真实接入)、WAL 分片文件(真追加 + 空洞检测)、LZ4 压缩
- 💾 OPFS 自研存储后端 — 纯浏览器文件系统,零 IndexedDB 依赖,二进制页面文件,schema 持久化,单文件 COW 原子写,崩溃残留自动清理
- 🔒 生产级数据安全 — WAL 原子写入 + 标准 CRC32 完整性校验(SSTable 整文件校验 + WAL 记录校验)、全库 AES-256-GCM 透明加密(PBKDF2 密钥派生 + salt 持久化 + 密码验证,v0.5.0 真实接线)、
RESTRICT 外键约束、崩溃恢复自愈
- 🔐 多标签页独占锁 — Web Locks API,第二个标签页打开同一库抛
ARIA_LOCKED(v0.5.0)
- 🛡 输入校验全覆盖 —
maxLength/min/max 约束、类型检查、必填验证
- 💾 多引擎架构 — Memory / IndexedDB / OPFS / Hybrid(write-through) / Aria 五种模式
- 📝 完整 SQL 支持 — SELECT/JOIN/子查询/GROUP BY/HAVING/ORDER BY/LIMIT/BETWEEN/IF NOT EXISTS/ALTER TABLE/TRUNCATE TABLE/UNION/INSERT...SELECT/事务语句/CREATE INDEX/EXISTS(v0.3.0)+ CASE WHEN/哈希连接/组提交(v0.3.1)+ 多标签页同步(v0.3.2)
- 🚰 流式查询 —
queryStream/stream() 逐行回调,Aria LSM 惰性扫描不物化结果集(v0.4.0)
- 🧩 派生表 —
FROM (SELECT ...) 子查询作为行源,多列 ON 哈希连接,COUNT(DISTINCT),NULLS FIRST/LAST(v0.4.0)
- 🔗 Query Builder API — 链式
.select().where().orderBy().limit().execute()
- 🔄 事务回滚 — Memory/IndexedDB/Hybrid/Aria 四引擎事务原子性,自动回滚,MVCC 版本链接入读写路径
- 🔗 外键级联 — ON DELETE + ON UPDATE(CASCADE / SET NULL / RESTRICT)全引擎支持,支持更新主键(v0.4.2)
- 🛡 崩溃恢复自愈 — 残缺 SSTable 打开自动跳过、
db.repair() 自愈(含孤儿页面清理与残留清理)、db.clearAll() 重置、迁移版本持久化(v0.4.2/v0.5.0)
- 🧵 关闭时序与后台任务加固 — 后台 flush/compaction 串行入队(close 排空后才关闭存储,失败显式报告
ARIA_BACKGROUND_ERROR)
- 📏 SSTable 编码修复 — 块大小按 UTF-8 字节精确计算、长度字段 u32、v1/v2 双格式兼容(v0.4.4)
- 🌲 RB-Tree 完整实现 — 标准红黑树插入+删除修复,O(log n) 保证
- ⚡ 性能优化 — SSTableReader 二分查找统一、IndexedDB 索引利用、crypto 实例化避免全局状态
- 🌐 浏览器兼容 — Chrome 80+ / Firefox 80+ / Safari 14+ / Edge 80+ / Node.js 16+
- 🧪 1022 测试 · 86.7% 覆盖率 — 62 套件 + 7 个 Playwright 真实 Chromium e2e,生产级质量保证
📦 安装
如果提示找不到包,先配置 scope registry(一次性):
CDN / 直接下载
或从 dist/ 目录下载:
metona-sqlark.js — UMD 开发版(含 sourcemap)
metona-sqlark.min.js — UMD 压缩版(~105KB,gzip ~27KB)
metona-sqlark.esm.js — ES Module
metona-sqlark.cjs — CommonJS
metona-sqlark.d.ts — TypeScript 类型声明
🚀 引入方式
ESM / TypeScript
CommonJS
Browser UMD
🚀 快速开始
📖 API 速览
数据库配置
| 属性 |
类型 |
默认 |
说明 |
name |
string |
'metona-sqlark' |
数据库名称 |
mode |
'memory' | 'disk' | 'hybrid' | 'aria' |
'hybrid' |
存储模式 🆕 aria |
diskEngine |
'indexeddb' | 'opfs' |
'indexeddb' |
磁盘引擎(aria 模式下为存储后端) |
version |
number |
1 |
版本号 |
maxRowsPerQuery |
number |
0 |
查询结果行数上限(0=不限制)✅ v0.2.5 生效 |
debug |
boolean |
false |
调试模式,输出详细日志 🆕 |
onError |
(error) => void |
— |
全局错误回调 🆕 |
aria |
AriaEngineConfig |
— |
AriaEngine 专属配置透传:walSyncMode/checkpointInterval/encryption/pageStorage/compression 等 🆕 v0.5.0 |
ColumnDef 列定义
| 属性 |
类型 |
说明 |
type |
'string'|'number'|'boolean'|'date'|'json' |
数据类型 |
primaryKey |
boolean |
主键 |
required |
boolean |
必填 |
unique |
boolean |
唯一约束 |
index |
boolean |
创建哈希索引 |
default |
unknown |
默认值 |
references |
string |
外键引用 'table.column' |
onDelete |
'CASCADE'|'SET NULL'|'RESTRICT' |
删除级联 ✅ v0.4.1 |
onUpdate |
'CASCADE'|'SET NULL'|'RESTRICT' |
更新级联(更新主键时触发)✅ v0.4.2 |
WHERE 操作符
| 操作符 |
含义 |
操作符 |
含义 |
$eq / 直接值 |
等于 |
$gt / $gte |
大于 / 大于等于 |
$ne |
不等于 |
$lt / $lte |
小于 / 小于等于 |
$in / $nin |
在列表中 |
$like |
模糊匹配 |
$and / $or / $not |
逻辑组合 |
|
|
核心方法
| 方法 |
说明 |
db.query(sql) |
执行 SQL 字符串 |
db.queryStream(sql, onRow) |
流式查询(逐行回调,不物化)🆕 |
db.table(name) |
获取表操作对象 |
db.defineTable(name, cols) |
定义表结构 |
db.transaction(fn) |
执行事务(自动回滚)🆕 |
db.repair() |
崩溃恢复自愈:校验清理损坏数据、恢复索引一致性(无需删库重建)🆕 v0.4.2 |
db.clearAll() |
清空全部数据与表结构(保留库本身,实例可继续使用)🆕 v0.4.2 |
db.exportTable(name) / db.exportAll() |
导出数据 JSON |
db.importTable(name, data) |
导入数据 |
db.backup() |
在线备份:全库一致性快照(Aria 引擎级备份 / 其余引擎回退 exportAll)🆕 v0.5.1 |
db.addMigration(v, fn) / db.migrateTo(v) |
数据迁移(版本持久化到库内,重启不重跑)🆕 v0.4.2 |
db.subscribe(table, fn) |
订阅表变更 |
db.on(hook, fn) |
注册钩子 (14 种,全部真实触发)🆕 v0.5.1 |
维护语句(v0.5.1 SQL 入口)
| 语句 |
说明 |
引擎支持 |
EXPLAIN SELECT ... |
输出查询计划(type/table/where/estimatedRows/actualTimeMs) |
全部 |
ANALYZE [TABLE] name |
收集表统计信息(行数/平均行大小/索引深度/列基数) |
Aria |
REINDEX [TABLE] name |
重建表二级索引 |
Aria |
VACUUM |
压缩 LSM + 清理 MVCC 碎片 |
Aria |
SAVEPOINT name |
创建嵌套事务保存点 |
Aria |
ROLLBACK TO [SAVEPOINT] name |
回滚到保存点 |
Aria |
RELEASE [SAVEPOINT] name |
释放保存点 |
Aria |
不支持的引擎执行维护语句抛 NOT_SUPPORTED。
连接池(v0.1.13)
| 静态方法 |
说明 |
MetonaSqlark.connect(config) |
获取或创建数据库实例(单例复用)🆕 |
MetonaSqlark.disconnect(name) |
释放连接(引用计数 -1)🆕 |
MetonaSqlark.disconnectAll() |
强制关闭所有连接 🆕 |
MetonaSqlark.getActiveConnections() |
获取活跃连接列表 🆕 |
React / Vue 集成
📊 存储模式对比
| 特性 |
Memory |
Disk (IndexedDB) |
Disk (OPFS) |
Hybrid |
Aria |
| 持久化 |
❌ 重启丢失 |
✅ IndexedDB |
✅ OPFS(schema 持久化) |
✅ 内存+磁盘 |
✅ 后端决定 |
| 事务回滚 |
✅ 快照 |
✅ 原子flush |
✅ 快照 |
✅ 双引擎 |
✅ MVCC |
| 二级索引 |
✅ Hash |
✅ Hash |
✅ Hash(重启恢复) |
✅ Hash |
✅ LSM(重启恢复) |
| 查询性能 |
⚡ O(1) PK |
🟡 O(1) PK |
🟡 O(1) PK |
⚡ O(1) PK |
⚡ O(log n) |
| 数据上限 |
内存限制 |
~2GB(IDB限制) |
~磁盘可用(页面化后大表可行) |
~2GB(IDB) |
内存限制 |
| 浏览器 |
全部 |
全部 |
Chrome/Edge 102+ / Firefox 111+ / Safari 15.2+ |
全部 |
全部 |
| 多标签页 |
— |
✅ |
❌(Web Locks 独占锁,v0.5.0) |
❌ |
✅ 锁保护 |
| 全库加密 |
— |
— |
— |
— |
✅ AES-GCM(v0.5.0) |
| 适用场景 |
缓存/测试 |
标准持久化 |
Chromium+ 持久化 |
速度+持久化 |
大规模/分析 |
| 测试覆盖 |
30+ |
30+ |
15+e2e |
15+ |
400+ |
Memory 模式
- 环境: 所有浏览器、Node.js
- 限制: 数据不持久化,页面刷新/进程重启后数据丢失
- 能力: 完整 CRUD、事务回滚、外键级联、二级索引、SQL 全支持
- 适用: 临时数据、单元测试、缓存层
Disk (IndexedDB) 模式
- 环境: 所有现代浏览器(Chrome/Firefox/Safari/Edge)、Node.js(fake-indexeddb)
- 限制: 受浏览器 IndexedDB 配额限制(通常 ~2GB),多标签页需处理版本冲突
- 能力: 完整 CRUD、事务原子性(单 IDB 事务包裹)、外键级联、onversionchange 感知
- 适用: 标准前端数据库持久化场景
Disk (OPFS) 模式
- 环境: Chrome 102+ / Edge 102+ / Firefox 111+ / Safari 15.2+(Origin Private File System)
- 限制: 每次写入重写整表 JSON 文件(大表性能差,不建议 >1000 行);多标签页并发写无保护(Hybrid 模式)
- 能力: 完整 CRUD、重启自动加载数据(空表/索引/schema 完整保留,v0.4.2)、事务回滚、并发写安全(内存快照一致)
- 适用: 小数据集持久化(大表请用 Aria + OPFS 页面化存储)
Hybrid 模式
- 环境: 所有浏览器
- 限制: 磁盘引擎决定底层限制(IndexedDB ~2GB / OPFS Chrome only)
- 能力: write-through 双写(内存+磁盘)、提交顺序保证(磁盘优先)、读从内存
- 适用: 需要内存速度 + 磁盘持久化的混合场景
Aria 模式
- 环境: 所有浏览器(后端可选 IndexedDB / OPFS / Memory)
- 限制: Memory 后端重启丢失;IndexedDB 后端受配额限制;OPFS 后端需 OPFS 支持(Chrome 102+ / Firefox 111+ / Safari 15.2+);同一库仅允许一个标签页打开(Web Locks 独占锁,第二个标签页抛
ARIA_LOCKED)
- 能力: LSM-Tree 存储引擎、SSTable 4KB 页面化物理存储(OPFS 后端默认启用,BufferPool LRU 缓存)、二级索引(跨重启恢复)、MVCC 事务、WAL 分片文件原子写入崩溃恢复(真追加 + 空洞检测)、ON UPDATE/DELETE 外键级联、Bloom Filter、全库 AES-GCM 透明加密(v0.5.0)、LZ4 压缩、Savepoint、EXPLAIN、ANALYZE、REINDEX、VACUUM、
repair() 自愈(含孤儿页面清理)
- 适用: 大规模数据分析、需要自研引擎可控性的高级场景
🌲 AriaEngine — 自研存储引擎
AriaEngine 是内置的页面式存储引擎,对标 SQLite 的设计理念:
AriaEngine 架构
| 特性 |
说明 |
| LSM-Tree |
MemTable (红黑树) → SSTable 多级索引,异步 Compaction(从存储兜底加载,不依赖缓存),写背压 |
| 页面化物理存储 |
OPFS 后端下 SSTable 存为 4KB 页面(pageStorage 自动启用):FileManager 分配 pageId、BufferPool LRU 缓存(256 页 ≈ 1MB 可控内存)、save 即落盘(WAL checkpoint 截断安全)、SSTableMeta.pageIds 持久化(旧整 value 数据兼容)v0.5.0 |
| WAL |
分片文件 __wal_%06d.bin(4MB 阈值切换)+ 真追加(createWritable keepExistingData);标准 CRC32 记录校验;full/batch/none 三种模式(full 真正同步);空洞检测截断;16MB 阈值自动 checkpoint(活跃事务期间不截断)v0.5.0 |
| 崩溃恢复 |
打开时完整性校验(残缺 SSTable 自动跳过并清理 + 整文件 CRC-32 校验)、WAL 按 key 扫描恢复(不丢记录)、恢复后自动重建二级索引 |
| 全库加密 |
encryption.password 配置 → EncryptedBackend 透明加解密(WAL/SSTable/Schema/元数据全密文);PBKDF2-SHA256 密钥派生 + salt/verifier 持久化;密码错误/数据篡改 → ARIA_DECRYPT_ERROR;明文库/加密库开关一致性检测 v0.5.0 |
| MVCC |
版本链 + 快照隔离,事务读写不互斥,提交/回滚按事务写入 key 精准清理,自动 GC |
| Bloom Filter |
FNV-1a + Murmur 双哈希,SSTable footer 序列化,查询时 probe |
| 二级索引 |
每列独立 LSM Tree,支持 $eq/$in/$gt/$lt 范围扫描,跨重启自动恢复,WAL 恢复后自动重建 |
| 多标签页锁 |
Web Locks API 库级独占锁(ifAvailable 不排队):第二个标签页抛 ARIA_LOCKED;不支持的环境降级无锁并告警 v0.5.0 |
| Compaction |
异步 Leveled Compaction,Level 0 > 8 触发同步背压,compactLevel public 接口 |
| OPFS Backend |
零外部依赖纯浏览器文件系统:单文件 COW 原子写、append 真追加、写队列失败不中断、close 排空、崩溃残留自动清理 v0.5.0 |
🛠 开发
📊 项目状态
| 指标 |
数值 |
| 测试用例 |
1022 |
| 测试套件 |
62(+7 Playwright e2e) |
| 行覆盖率 |
86.7% |
| SQL 关键字 |
36 |
| 存储引擎 |
5(Memory / IndexedDB / OPFS / Hybrid / Aria) |
🌐 浏览器兼容性
| 浏览器 |
最低版本 |
Memory |
IndexedDB |
OPFS |
Web Locks |
Aria |
| Chrome |
80+ |
✅ |
✅ |
✅ (102+) |
✅ (69+) |
✅ |
| Firefox |
80+ |
✅ |
✅ |
✅ (111+) |
✅ (96+) |
✅ |
| Safari |
14+ |
✅ |
✅ |
✅ (15.2+) |
✅ (15.4+) |
✅ |
| Edge |
80+ |
✅ |
✅ |
✅ (102+) |
✅ (79+) |
✅ |
| Node.js |
16+ |
✅ |
✅ (fake-idb) |
❌ (测试用 mock) |
❌ |
✅ |
OPFS 支持说明(v0.4.5 更新): Chromium(Chrome/Edge 102+)、Firefox 111+、Safari 15.2+
均已支持基础 OPFS API(createWritable 原子写)。OPFS 无跨文件事务,
AriaEngine 以 WAL 分片单文件原子写 + 空洞检测截断保证崩溃一致性。
多标签页保护(v0.4.5): AriaEngine 打开库时通过 Web Locks API 获取库级独占锁,
第二个标签页打开同一库会抛 ARIA_LOCKED。Web Locks 不可用的环境降级为无锁并告警
(仅理论上,现代浏览器均支持)。
📂 项目结构
📄 License
MIT © MetonaTeam