TypeScript 原生构建,4 种存储模式 + 3 种存储后端,支持完整 SQL 查询。
零运行时依赖,开箱即用。AriaEngine 自研引擎:LSM-Tree + WAL 同步 + MVCC。
多种方式,按需选择
专为前端打造的数据库引擎
模式:Memory / Disk / Hybrid / AriaEngine;后端:OPFS / KVStore / Memory。Aria 是自研 LSM-Tree 页面式引擎,支持 WAL 同步崩溃恢复与事务回滚(版本链仅作事务内 undo,事务串行 —— 非 MVCC 快照隔离)。
手写递归下降 SQL 解析器。SELECT / INSERT / UPDATE / DELETE / JOIN / GROUP BY / HAVING / DISTINCT / 子查询 / ALTER TABLE / TRUNCATE TABLE。
自研 LSM-Tree 存储引擎:SSTable 4KB 页面化物理存储(BufferPool LRU)、WAL 分片文件原子写入、__aria_manifest 单一提交点(数据落盘 → 元数据原子提交 → 才截断 WAL)、全库 AES-GCM 透明加密、标准 CRC-32 完整性校验、MVCC 快照回滚、二级索引跨重启恢复、ON UPDATE/DELETE 外键级联、崩溃恢复自愈。
beginTransaction / commitTransaction / rollbackTransaction 三件套。失败自动回滚,Memory 快照 + KVStore 原子日志 + Aria MVCC 版本链。
IN (SELECT ...) + 标量子查询。ALTER TABLE ADD/DROP COLUMN 动态修改表结构,TRUNCATE TABLE 快速清空。
references + ON DELETE / ON UPDATE CASCADE · SET NULL · RESTRICT(更新主键级联更新子表)。React/Vue hooks 表名合法性校验,防 SQL 注入。
异常退出后无需删库重建:整文件 CRC-32 校验 + 打开自动跳过损坏 SSTable,并按 WAL 水位重放已提交事务;getRecoveryReport() 如实给出被丢弃的 SSTable、WAL 空洞与是否怀疑丢数据。介质读故障与"文件不存在"分开处理(前者抛 ARIA_SSTABLE_READ_FAILED,绝不误删元数据);元数据整体损坏时显式拒绝打开(ARIA_MANIFEST_CORRUPT),而不是当成空库。db.repair() 只在 manifest 健康时回收孤儿页面并重建索引。
MetonaSqlark.connect() 单例复用。SSTableReader 二分查找统一、KVStore 内存热路径 O(1) 读、crypto 实例化。
14 种生命周期钩子全部真实触发(Table API 与 SQL 双路径):beforeCreateTable / afterInsert / beforeQuery / afterTransaction……按优先级注册。
纯 TypeScript 实现,不依赖任何第三方库。UMD/ESM/CJS 多格式输出,min 产物实测 251,731 字节 / gzip 63,431 字节。
COUNT / SUM / AVG / MIN / MAX 五大聚合函数,GROUP BY + HAVING 子句,DISTINCT 去重。
encryption.password 一键启用 AES-256-GCM 全库透明加密(密码验证 + 篡改检测)。Web Locks 独占锁:第二个标签页打开同一库抛 ARIA_LOCKED。
EXPLAIN 查询计划 · ANALYZE 表统计 · REINDEX 重建索引 · VACUUM 压缩 · SAVEPOINT 嵌套事务保存点 — 全部原生 SQL 语法。
内置版本迁移系统,addMigration + migrateTo API。导入导出支持单表/全库 JSON 序列化,db.backup() 全库导出(逐表读取)。
subscribe() 订阅表变更。React useQuery / Vue useSqlarkQuery 开箱即用。
链式 API + TypeScript 泛型。.select().where().innerJoin().orderBy().limit() — 类型安全,IDE 友好。
queryStream 逐行回调真惰性扫描(v0.7.4:Aria 引擎迭代器化,limit 提前终止,大表内存 O(1))。FROM (SELECT ...) 派生表、多列哈希连接、COUNT(DISTINCT)、NULLS FIRST/LAST。
清晰的分层结构,各模块职责单一
┌──────────────────────────────────────────────────────────┐ │ MetonaSqlark / MeSqlark │ │ create() · query() · table() · tx() │ ├──────────┬──────────┬──────────┬──────────┬──────────────┤ │ SQL Parser │ QueryBuilder │ Transaction│ Plugin │ Migration │ │ Lexer → │ .select() │ Manager │ Manager │ System │ │ Parser │ .where() │ │ 14 hooks │ │ ├──────────┴──────────┴──────────┴──────────┴──────────────┤ │ QueryExecutor (AST → Results) │ │ JOIN · GROUP BY · HAVING · DISTINCT · Subquery │ ├──────────────────────────────────────────────────────────┤ │ IStorageEngine Interface │ ├──────────┬──────────┬──────────┬──────────┬──────────────┤ │ Memory │ KVStore │ OPFS │ Hybrid │ AriaEngine │ │ Engine │ Engine │ Engine │ Engine │ LSM-Tree │ │ (Map) │ (自研KV) │ (OPFS) │ (W-Thru) │ WAL + MVCC │ └──────────┴──────────┴──────────┴──────────┴──────────────┘
SQL + Query Builder 双 API — JOIN · 子查询 · 聚合 · 事务回滚 · 外键级联 · 连接池 · AriaEngine · ALTER TABLE · TRUNCATE
// 创建数据库 — MeSqlark 是别名,完全等价 const db = await MetonaSqlark.create({ name: 'my-app', mode: 'hybrid' }); // 定义表结构 — 支持外键级联 await db.defineTable('users', { id: { type: 'string', primaryKey: true }, name: { type: 'string', required: true }, age: { type: 'number', default: 0 }, email: { type: 'string', unique: true, index: true }, }); // SQL 查询 await db.query("INSERT INTO users VALUES ('1', 'Alice', 30, 'alice@demo.com')"); const rows = await db.query('SELECT * FROM users WHERE age > 18 ORDER BY name'); // Query Builder — 类型安全,链式调用 const rows2 = await db.table('users') .select(['name', 'age']).where({ age: { $gt: 18 } }) .orderBy('name').limit(10).execute(); // JOIN 多表关联 await db.query(`SELECT u.name, o.product, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id WHERE o.amount > 100`); // GROUP BY 聚合分析 await db.query(`SELECT dept, COUNT(*) as cnt, AVG(salary) as avg FROM employees GROUP BY dept HAVING COUNT(*) > 1`); // 事务 — 失败自动回滚 await db.transaction(async (trx) => { await trx.table('users').insert({ id: '3', name: 'Charlie' }); await trx.table('orders').insert({ id: 'o1', userId: '3', amount: 99 }); // 任何一步失败 → 自动回滚 }); // 子查询 — IN (SELECT ...) await db.query(`SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100)`); // 连接池 — 单例复用,避免重复打开底层存储 const db1 = await MetonaSqlark.connect({ name: 'my-app' }); const db2 = await MetonaSqlark.connect({ name: 'my-app' }); // db1 === db2(复用已有实例) await db2.disconnect(); // 引用计数 -1,归零时自动 close
MetonaSqlark 的核心指标