左帮右臂SQLite双层工业数据私有存储系统 V1.0
软件说明书
| 项目 | 内容 |
|---|---|
| 软件名称 | 左帮右臂SQLite双层工业数据私有存储系统 |
| 版本号 | V1.0 |
| 著作权人 | 北京左帮右臂人工智能技术有限公司 |
| 统一社会信用代码 | 91110114MAKJ1UC63J |
| 编写日期 | 2026年7月 |
| 开发完成日期 | 2026年6月15日 |
| 首次发表日期 | 未发表 |
目录
- 一、软件概述
- 1.1 研发背景
- 1.2 核心功能
- 1.3 应用场景
- 1.4 系统定位与适用行业
- 1.5 与同类方案的对比优势
- 二、软硬件运行环境
- 2.1 硬件环境
- 2.2 软件环境
- 2.3 环境变量配置
- 2.4 容器化与网络端口说明
- 三、软件系统架构
- 3.1 总体架构
- 3.2 双层存储架构图
- 3.3 数据流转逻辑
- 3.4 模块依赖与启动顺序
- 3.5 容错与后端自动回退机制
- 四、核心功能详细说明
- 4.1 sql.js兼容层(sqlite-compat.js)
- 4.2 SQLite/MySQL双后端适配(db-adapter.js)
- 4.3 数据库管理(database1.js)
- 4.4 多租户数据库隔离(tenant-db.js)
- 4.5 标准库只读 + 私有库可读写 + 数据合并同步(sync-service.js)
- 4.6 跨后端数据一致性保障
- 五、软件创新点与优势
- 5.1 数据库即文件
- 5.2 拷贝式迁移
- 5.3 无需DBA运维
- 5.4 双层隔离的数据主权保障
- 5.5 防抖批量写入性能优化
- 5.6 延迟代理零改动的异步兼容
- 5.7 SQLite/MySQL双后端无缝切换
- 5.8 创新点综合对照表
- 六、软件操作步骤与使用说明(含操作界面截图)
- 6.1 初始化私有数据库
- 6.2 数据写入与事务
- 6.3 数据查询
- 6.4 租户标识解析与多租户路由
- 6.5 建立数据表与索引
- 6.6 数据导入与批量写入
- 6.7 数据查询与统计
- 6.8 备份与恢复
- 七、典型应用场景案例(含真实运行界面)
- 7.1 场景一:双层私有数据初始化
- 7.2 场景二:成本优化数据落库与查询
- 7.3 场景三:平台统一数据服务
- 7.4 场景四:多租户SaaS托管数据隔离
- 7.5 场景五:标准库规则模板增量下发
- 7.6 场景六:设备预测性维护数据采集
- 7.7 场景七:质量NCR/CAPA全过程管理
- 7.8 场景八:AI代理自学习数据底座
- 八、数据接口与集成说明
- 8.1 接口总览
- 8.2 initStorage() 初始化接口
- 8.3 put() 写入接口
- 8.4 get() 读取接口
- 8.5 query() 参数化查询接口
- 8.6 集成调用范式与最佳实践
- 九、核心功能模块详述与部署运维(含真实运行界面)
- 9.1 双层存储初始化
- 9.2 数据写入与路由
- 9.3 查询与回溯
- 9.4 部署与运维
- 十、版本更新说明
- 十一、常见问题与故障排查
- 11.1 数据库连接失败,提示"无法打开"?
- 11.2 大表查询变慢,如何优化?
- 11.3 如何做数据备份与恢复?
- 11.4 多租户数据是否隔离?
- 11.5 数据文件损坏能否恢复?
- 11.6 如何验证存储层确实在工作?
- 11.7 并发写入会锁表吗?
- 11.8 支持的数据类型?
- 11.9 错误码对照表
- 十二、术语与缩略语
- 十三、技术参数与性能指标
- 十四、参数配置说明
- 十五、部署与运维详细步骤
- 十六、安全机制
- 十七、性能基准
- 著作权人信息
一、软件概述
1.1 研发背景
在工业制造领域,企业每天产生大量的工艺数据、质量检验记录、库存数据、设备运行数据等核心业务数据。这些数据是企业的重要资产,涉及工艺机密、供应链信息和生产know-how。传统工业数据管理方案存在以下痛点:
- 数据主权风险:工业数据存储在第三方云数据库或共享数据库中,企业无法完全掌控数据的物理边界,存在数据泄露和合规风险。
- 运维门槛高:传统MySQL/Oracle等数据库需要专业DBA进行安装、配置、备份、优化,中小制造企业难以承担专职运维成本。
- 多租户隔离困难:SaaS模式下多客户数据混存于同一数据库,难以实现物理级隔离,一旦发生越权访问将波及所有租户。
- 迁移成本高昂:数据库迁移需要导出导入、停机切换、数据校验等复杂流程,影响业务连续性。
- 离线场景受限:工业现场(车间、产线)网络环境不稳定,依赖中心数据库的应用在网络中断时无法工作。
基于上述背景,北京左帮右臂人工智能技术有限公司研发了"左帮右臂SQLite双层工业数据私有存储系统 V1.0",以SQLite文件数据库为核心,构建标准库与私有库双层隔离架构,实现工业数据的私有化、文件化、轻量化存储。
1.2 核心功能
本系统的核心功能为双层隔离存储:
- 标准库(只读层):存储行业通用规则、模板、提示词等标准数据,以独立SQLite文件(sciot_import.db)形式分发,各租户共享同一份标准库但仅具备只读权限。
- 私有库(可读写层):每个租户拥有独立的SQLite文件(data/tenants/
.db),存储该客户的全部业务数据,与其他租户和标准库物理隔离。
系统通过同步服务将标准库内容合并到各租户私有库,实现"标准下发、私有定制"的数据管理范式。
1.3 应用场景
本系统适用于以下工业场景:
- 制造企业工艺数据管理:管理AML模板、工艺规程、PPS工艺文件、BOM清单等工艺数据。
- 质量管理体系:管理进料检验、不合格品报告(NCR)、纠正预防措施(CAPA)等质量数据。
- 库存与供应链管理:管理库存物品、出入库记录、供应商信息等供应链数据。
- 设备预测性维护:采集传感器数据(振动、温度、电流、转速、压力),管理设备台账和健康评分。
- 多客户SaaS托管:单个服务实例托管多个客户,每客户数据独立文件隔离。
- AI代理数据底座:为AI代理提供操作日志记录、自学习数据基础和业务数据查询能力。
1.4 系统定位与适用行业
本系统定位为面向工业制造领域的轻量级、私有化、文件型数据底座,介于"纯内存缓存"与"重型关系型数据库集群"之间,填补了中小制造企业在"既要数据主权、又要零运维成本、还要离线可用"三者之间的现实空白。它不试图替代企业级数据仓库或时序数据库在超大规模分析场景中的作用,而是专注于为业务应用、数字员工、AI代理提供稳定、可控、可审计的私有存储能力。
适用行业与典型用户包括:
- 离散制造企业:机械加工、电子装配、汽车零部件等,需要管理BOM、工艺规程、质量记录。
- 流程制造企业:化工、食品、医药等,需要管理批次、配方、检验数据,并满足合规留痕。
- 设备制造与运维服务商:需要采集并管理设备IoT传感器数据,支撑预测性维护。
- 工业互联网平台商:以多租户方式托管多家客户的工业数据,要求物理级隔离。
- AI/数字员工解决方案商:需要为智能体提供长期记忆、操作日志与业务数据检索底座。
1.5 与同类方案的对比优势
为帮助读者理解本系统的差异化价值,下表从部署复杂度、数据主权、迁移成本、多租户隔离、离线可用、运维门槛六个维度,对本系统与三类典型方案进行对比:
| 维度 | 传统MySQL/Oracle | 中心化云数据库 | 内存型KV缓存 | 本系统(SQLite双层私有存储) |
|------|------------------|----------------|--------------|------------------------------|
| 部署复杂度 | 高(需安装服务进程) | 中(需开通账号) | 低 | 极低(npm install 即可) |
| 数据主权 | 弱(集中托管) | 弱(第三方控制) | 弱 | 强(文件即数据库,物理可控) |
| 迁移成本 | 高(导出导入停机) | 中(依赖厂商) | 不适用 | 极低(复制文件即迁移) |
| 多租户隔离 | 逻辑隔离为主 | 逻辑隔离为主 | 逻辑隔离 | 物理文件隔离 |
| 离线可用 | 需自建机房 | 依赖网络 | 数据易失 | 完全单机可用 |
| 运维门槛 | 需专职DBA | 需平台知识 | 低 | 无需DBA |
综上,本系统在"数据主权 + 零运维 + 离线可用"三角约束下具备明显优势,尤其适合对数据物理边界敏感、又无力承担重型数据库运维成本的中小制造企业。
二、软硬件运行环境
2.1 硬件环境
| 项目 | 最低配置 | 推荐配置 |
|------|----------|----------|
| CPU | 双核 1.6GHz | 四核 2.0GHz 及以上 |
| 内存 | 2GB | 4GB 及以上 |
| 磁盘 | 10GB 可用空间 | 50GB SSD 及以上 |
| 网络 | 无需持续联网 | 局域网/广域网均可 |
说明:由于采用sql.js纯JS引擎,本系统对CPU无特殊指令集要求;内存消耗主要取决于同时打开的租户库数量与单库数据规模,推荐配置可支撑数十个租户库同时驻留内存。磁盘方面,SQLite单库理论容量上限约140TB,但实测建议单库控制在50GB以内以获得最佳查询与备份性能。
2.2 软件环境
| 项目 | 要求 |
|------|------|
| 操作系统 | Windows 10/11、Windows Server 2016+、Linux(CentOS/Ubuntu)、macOS |
| 运行时 | Node.js 16.0 及以上 |
| 核心依赖 | sql.js 1.10+(纯JS SQLite引擎,无需编译原生模块) |
| 可选依赖 | mysql2(启用MySQL后端时需要) |
| 数据库后端 | SQLite(默认,文件型)或 MySQL 5.7+/8.0(可选) |
| 浏览器 | Chrome 90+、Edge 90+、Firefox 88+(前端管理界面) |
说明:sql.js为WebAssembly/纯JS实现的SQLite引擎,故在Windows、Linux、macOS三平台行为高度一致,无需针对平台编译原生模块(这与better-sqlite3、node-sqlite3等需要node-gyp编译的方案形成鲜明对比)。启用MySQL后端时需额外安装mysql2驱动,且目标MySQL服务需开放相应端口与账号权限。
2.3 环境变量配置
| 变量名 | 说明 | 默认值 |
|---|---|---|
| DB_BACKEND | 数据库后端选择(sqlite/mysql) | sqlite |
| DB_MYSQLDB_HOST | MySQL主机地址 | localhost |
| DB_MYSQLDB_PORT | MySQL端口 | 3306 |
| DB_MYSQLDB_USER | MySQL用户名 | root |
| DB_MYSQLDB_PASSWORD | MySQL密码 | - |
| DB_MYSQLDB_DATABASE | MySQL数据库名 | bossagents |
| DEFAULT_TENANT | 默认租户标识 | default |
| GST_BACKEND_MODE | 后端模式(local/proxy) | local |
| DATA_DIR | 数据目录 | ./data |
| WB_DEBUG | 调试模式(1/0) | 0 |
2.4 容器化与网络端口说明
本系统可运行于裸机Node.js进程,亦可打包为容器镜像运行。容器化部署时需注意以下要点:
- 数据卷持久化:必须将宿主机的持久化目录(对应
DATA_DIR)挂载为卷(volume),否则容器重建后.db文件将随容器层一同丢失。建议使用命名卷或绑定挂载到SSD磁盘路径。 - 端口暴露:前端管理界面与HTTP数据接口默认监听服务进程端口(由宿主应用决定),容器需通过
-p映射该端口到宿主机;若仅内部调用,可限制为仅集群内网可达。 - 时区一致性:由于SQL方言中时间函数(
datetime('now','localtime')与 MySQLNOW())依赖运行环境时区,务必保证容器与宿主时区一致(推荐统一设为Asia/Shanghai),避免因时区漂移导致时间字段错乱。 - 资源限制:建议为容器设置内存上限不低于推荐配置(4GB),并预留磁盘I/O带宽给防抖批量写盘与备份复制操作。
三、软件系统架构
3.1 总体架构
系统采用分层架构设计,自下而上分为四层:
┌─────────────────────────────────────────────────────────────────────┐
│ 应用业务层 │
│ (项目管理/质量检验/库存管理/设备维护/AI代理/工艺规程...) │
├─────────────────────────────────────────────────────────────────────┤
│ 数据库管理层 (database1.js) │
│ (DatabaseManager单例 / 40+业务表 / 索引 / 迁移 / 懒加载) │
├──────────────────────┬──────────────────────────────────────────────┤
│ 租户管理层 │ 同步服务层 (sync-service.js) │
│ (tenant-db.js) │ (标准库→私有库 / 规则/模板/Prompt同步) │
├──────────────────────┴──────────────────────────────────────────────┤
│ 双后端适配层 (db-adapter.js) │
│ (SQLite/MySQL切换 / SQL方言转换 / 故障自动回退) │
├─────────────────────────────────────────────────────────────────────┤
│ SQLite兼容层 (sqlite-compat.js) │
│ (sql.js引擎 / 防抖批量写入 / 事务优化 / 延迟代理 / 进程退出保护) │
├─────────────────────────────────────────────────────────────────────┤
│ 物理存储层 (文件系统) │
│ data/bossagents.db ← 默认租户/核心业务库 │
│ data/tenants/<cid>.db ← 各租户私有库 │
│ data/sciot_import.db ← 标准库(只读分发) │
└─────────────────────────────────────────────────────────────────────┘
架构解读:应用业务层通过数据库管理层访问数据;数据库管理层在内部按租户拆分库文件,并通过同步服务层将标准库内容下发到各私有库;双后端适配层屏蔽SQLite与MySQL差异;最底层的SQLite兼容层以sql.js引擎直接读写文件系统上的.db文件,实现"数据库即文件"的设计哲学。
3.2 双层存储架构图
┌───────────────────────────────┐
│ 标准库(只读层) │
│ data/sciot_import.db │
│ ┌─────────────────────────┐ │
│ │ sciot_rules_v2 (规则) │ │
│ │ sciot_templates (模板) │ │
│ │ prompt_templates (提示词)│ │
│ │ sciot_business_prompts │ │
│ └─────────────────────────┘ │
└───────────────┬───────────────┘
│ 同步服务
│ (sync-service.js)
│ 增量合并 / 强制更新
┌───────────────▼───────────────┐
│ 租户A私有库(可读写层) │
│ data/tenants/customerA.db │
│ ┌─────────────────────────┐ │
│ │ user_rules (用户规则) │ │
│ │ user_templates (用户模板)│ │
│ │ user_prompts (用户提示词)│ │
│ │ 40+业务表 (项目/质量/...)│ │
│ │ sync_state (同步状态) │ │
│ └─────────────────────────┘ │
└───────────────────────────────┘
┌───────────────────────────────┐
│ 租户B私有库(可读写层) │
│ data/tenants/customerB.db │
│ ┌─────────────────────────┐ │
│ │ user_rules │ │
│ │ user_templates │ │
│ │ 40+业务表 │ │
│ └─────────────────────────┘ │
└───────────────────────────────┘
(各租户完全物理隔离,互不可见)
3.3 数据流转逻辑
系统数据流转遵循以下逻辑:
- 标准库加载:系统启动时,sync-service.js通过
getStandardDB()加载标准库SQLite文件(sciot_import.db),以只读方式打开。
- 标准数据读取:从标准库读取三类数据:
- 规则(
loadStandardRules):从sciot_rules_v2表读取规则定义(名称、类型、条件、动作、严重等级等)。 - 模板(
loadStandardTemplates):从sciot_templates表读取AML模板(字段定义、关系类型、生命周期等)。 - 提示词(
loadStandardPrompts):从prompt_templates和sciot_business_prompts两表读取AI提示词模板。
- 增量同步到私有库:
syncStandardToUser(userId, options)执行同步:
- 逐条检查私有库中是否已存在相同
standard_id的记录。 - 不存在则INSERT新记录(source标记为'standard_copy')。
- 已存在且force=true且来源为'standard_copy'则UPDATE更新。
- 已存在且非force则跳过。
- 更新
sync_state表记录同步时间和计数。
- 业务数据读写:应用层通过DatabaseManager单例对私有库执行CRUD操作,所有写操作经防抖批量写入磁盘。
- 多租户路由:每次HTTP请求通过
resolveCustomerId(req)从请求头/查询参数解析租户标识,getTenantDbForRequest(req)返回对应的租户数据库实例。
3.4 模块依赖与启动顺序
各核心模块的依赖关系与推荐初始化顺序如下,理解该顺序有助于排障与性能调优:
- sqlite-compat.js(最底层):最先就绪。它在
require阶段尝试同步获取Database构造函数,若为Promise(v1.10+)则挂载_initPromise。上层模块在任何时刻调用createDatabase()都能通过延迟代理获得可用实例。 - db-adapter.js(适配层):依赖sqlite-compat与mysql2(可选)。通过
init()完成后端选择与故障回退,是database1与tenant-db获取连接的统一入口。 - database1.js(管理层):依赖db-adapter。DatabaseManager以懒加载单例形式存在,首次访问
db属性时触发_ensureDb()→init()→建表→建索引→迁移。 - tenant-db.js(隔离层):依赖db-adapter与sqlite-compat。负责按customerId打开/缓存独立
.db文件,并提供sanitize与解析逻辑。 - sync-service.js(同步层):依赖database1与tenant-db。在业务首次需要标准数据时触发标准库读取与增量同步。
该分层保证了"下层先于上层可用、上层调用下层无需感知异步",是整个系统高内聚低耦合的关键。
3.5 容错与后端自动回退机制
系统在多处实现了容错设计,确保单点故障不致整体不可用:
- MySQL初始化失败回退SQLite:当
DB_BACKEND=mysql但MySQL连接失败(账号错误、网络不可达、版本不兼容)时,db-adapter.js捕获异常并自动切换_backend='sqlite',业务代码无需任何改动即可继续以文件库运行。 - 未初始化容错:
createDatabase()在init()未完成时,SQLite模式直接require创建实例;MySQL模式若Worker未就绪则临时回退SQLite,待init完成后切换。 - 进程退出保护:sqlite-compat监听
exit、SIGINT、SIGTERM、uncaughtException,退出前若有脏数据则紧急saveNow(),避免写入窗口内数据丢失。 - 迁移容错:
_runMigrations()通过try-catch忽略"列已存在"错误,重复执行迁移脚本安全幂等。
四、核心功能详细说明
4.1 sql.js兼容层(sqlite-compat.js)
本模块是整个存储系统的基石,使用sql.js(纯JavaScript实现的SQLite引擎)替代传统better-sqlite3,消除了原生模块编译依赖,实现跨平台零编译部署。
#### 4.1.1 同步/异步双模初始化
sql.js v1.10+的require('sql.js')()返回Promise而非同步对象。兼容层采用双模初始化策略:
- 同步路径:尝试同步获取Database构造函数,若返回Promise则挂载then回调提前触发异步解析。
- 异步路径:
init()函数await已挂载的Promise,避免重复初始化。
// 同步路径尝试
const sqlModule = require('sql.js')();
if (sqlModule && typeof sqlModule.Database === 'function') {
_Database = sqlModule.Database; // 旧版同步就绪
} else if (sqlModule && typeof sqlModule.then === 'function') {
_initPromise = sqlModule.then(mod => { _Database = mod.Database; }); // v1.10+
}
设计价值:上层业务代码(database1、tenant-db、sync-service)始终按"同步API"书写,无需为sql.js的异步化做大规模改造。这正是延迟代理(4.1.4)与双模初始化协同带来的工程收益——它在保持代码简洁的同时,享受到了sql.js纯JS引擎的跨平台、零编译优势。
#### 4.1.2 防抖批量写入
传统sql.js每次写操作后需调用db.export()导出二进制并写入文件,高频写入性能极差。本系统实现防抖保存机制:
- 脏标记(_dirty):写操作仅标记脏位,不立即写盘。
- 防抖定时器(_saveTimer):默认100ms延迟,连续写操作合并为一次磁盘写入。
- 立即保存(save(0)):事务COMMIT等关键场景传delay=0强制立即写盘。
- 只读不保存:
all()和get()只读操作不触发save。
function save(delayMs) {
_dirty = true;
if (_saveTimer) clearTimeout(_saveTimer);
if (delayMs === 0) saveNow(); // 立即写盘
else _saveTimer = setTimeout(saveNow, delayMs || 100); // 防抖
}
工程意义:在工艺数据高频采集、质量记录批量落库等场景下,若每次写操作都导出整个数据库二进制(可能数十MB),磁盘I/O将成为瓶颈。防抖机制将"每秒数百次写"合并为"每100ms一次写",I/O次数下降1~2个数量级,同时只读查询完全零写盘,互不干扰。
#### 4.1.3 事务优化
transaction(fn)包装用户函数,仅在COMMIT成功后调用save(0)一次写入磁盘,而非事务内每条语句都写盘:
transaction(fn) {
return function(...args) {
db.exec('BEGIN');
fn(...args); // 用户函数内多次写操作均不写盘
db.exec('COMMIT');
save(0); // 仅COMMIT后写盘一次
};
}
说明:当业务需要在单事务内批量导入上千条记录时,事务优化保证这些写操作只在最终COMMIT时落盘一次,既保证了原子性(要么全成功要么全回滚),又避免了N次磁盘导出开销。
#### 4.1.4 延迟代理(Lazy Proxy)
当createDatabase()在init()完成前被调用时,返回一个延迟代理对象。代理内部触发后台init,init完成后自动创建真实实例并转发调用,旧代码无需任何改动:
const proxy = {
_isProxy: true,
_realDb: null,
async _ensureReady() {
await init();
this._realDb = _createRealInstance(this._dbPath);
},
prepare(sql) { if (this._realDb) return this._realDb.prepare(sql); throw... },
// ...
};
proxy._ensureReady().catch(...); // 后台触发,不阻塞
return proxy;
说明:延迟代理是"异步引擎、同步API"这一设计目标的最终落点。它让上层业务在sql.js异步加载期间即可拿到"看起来像数据库"的对象并立即调用方法,真正初始化完成后再无缝切换到真实实例,调用方对此完全无感。
#### 4.1.5 进程退出保护
监听exit、SIGINT、SIGTERM、uncaughtException四个事件,进程退出时若有未保存的脏数据,紧急执行saveNow()持久化,防止数据丢失。
补充:该保护对uncaughtException(未捕获异常)的监听尤为重要——当业务代码抛出未预期异常时,进程虽将退出,但已写入内存、尚未落盘的脏数据仍会被紧急保存,最大限度降低数据丢失窗口。
#### 4.1.6 Statement封装
Statement类封装sql.js的prepared statement,提供与better-sqlite3兼容的run()/all()/get()接口:
- 参数安全处理:null值透传、对象自动JSON序列化、is_null标记处理。
- 自动重准备(_reprepare):每次执行后重新prepare,避免statement状态污染。
- run()返回
{changes, lastInsertRowid}标准结果。
说明:自动重准备解决了sql.js原生statement在多次绑定不同参数后状态残留的问题,是参数化查询稳定防注入的基础保障。
#### 4.1.7 独立实例(createDatabaseFresh)
createDatabaseFresh(dbPath)绕过实例缓存创建独立实例,专供规则引擎等需要独占内存状态的模块使用,避免被其他模块的同路径实例干扰。
说明:默认createDatabase()会按路径缓存实例(见术语"实例映射 _instances"),多个模块共享同一内存库。但规则引擎在内存中维护增量编译状态,与其他读写混用同一实例可能引发状态污染,故提供Fresh接口获得独占实例。
4.2 SQLite/MySQL双后端适配(db-adapter.js)
#### 4.2.1 后端选择与自动回退
通过环境变量DB_BACKEND选择后端(sqlite/mysql),同时兼容n8n的DB_TYPE环境变量。MySQL后端初始化失败时自动回退到SQLite:
if (backend === 'mysql') {
const ok = await _adapter.init();
if (!ok) {
console.error('MySQL后端初始化失败,回退到SQLite');
_backend = 'sqlite';
_adapter = require('./sqlite-compat');
}
}
#### 4.2.2 SQL方言工具
提供方言无关的SQL片段生成函数,业务层无需关心后端差异:
nowExpr():MySQL返回NOW(),SQLite返回datetime('now','localtime')。autoIncrementPK():MySQL返回INT AUTO_INCREMENT PRIMARY KEY,SQLite返回INTEGER PRIMARY KEY AUTOINCREMENT。textPK():MySQL返回VARCHAR(255) PRIMARY KEY,SQLite返回TEXT PRIMARY KEY。getConvertSQL():获取SQL方言转换函数。
工程价值:业务层在建表、写时间字段时统一调用上述工具函数,而非硬编码后端语法,从而一份代码可在SQLite与MySQL两种后端间无缝切换,无需为迁移重写SQL。
#### 4.2.3 未初始化容错
createDatabase()在init()未完成时:
- SQLite模式:直接require并创建实例(sql.js可能已同步加载)。
- MySQL模式:若Worker已就绪则使用,否则临时回退SQLite,待init()完成后切换。
4.3 数据库管理(database1.js)
#### 4.3.1 DatabaseManager类
采用懒加载单例模式:
- 首次访问
db属性时通过_ensureDb()创建连接。 - 后端切换(SQLite→MySQL)时自动关闭旧连接、重建新连接。
- 首次
_ensureDb()时自动执行init():建表→建索引→执行迁移。 - monkey-patch
_ensureDb实现首次访问自动初始化,避免遗忘调用init。
说明:懒加载单例避免了进程启动时冗余建连,也保证了"首次真正用库时才自动建表迁移"这一零运维体验——运维人员无需手工执行DDL脚本。
#### 4.3.2 业务表体系
系统管理40+业务表,覆盖工业制造全链路:
| 业务域 | 表名 | 说明 |
|--------|------|------|
| 元数据管理 | aml_templates, aml_properties | AML模板与属性定义 |
| 对象建模 | item_types, item_type_properties | 对象类元数据与属性 |
| 项目管理 | projects, project_tasks | 项目与任务 |
| 文档管理 | documents | 文档版本管理 |
| 质量管理 | quality_inspections, quality_ncr, quality_capa | 检验/NCR/CAPA |
| 库存管理 | inventory_items, inventory_transactions | 库存与出入库 |
| 供应链 | vendors, customers, orders | 供应商/客户/订单 |
| 设备维护 | sensor_data, devices | IoT数据与设备台账 |
| AI代理 | ai_action_logs, SCSAI_items | AI操作日志与SCSAI对象 |
| 工艺规程 | process_industries, process_templates, process_specs | 工艺规程智能生成 |
| 工艺知识 | process_knowledge_entries, process_knowledge_history | 知识库与版本历史 |
| PPS同步 | sccapp_tech_files, sccapp_procs, sccapp_steps, sccapp_tech_data等 | PPS工艺文件体系 |
| 数据资产 | data_assets, data_asset_items, extraction_jobs | 数据资产与抽取 |
| BOM管理 | bom_headers, bom_items, bom_demo_entries | BOM清单 |
| 人力资源 | employees | 员工信息 |
| 客诉管理 | complaints | 客户投诉 |
| 导入管理 | import_records, import_progress | 数据导入记录 |
说明:上述表均为系统首次访问时由DatabaseManager自动创建,覆盖从对象建模、项目管理到质量、库存、设备、AI代理的完整工业数据链路,是"工业数据私有存储"名副其实的体现。
#### 4.3.3 索引体系
为所有高频查询字段创建索引,涵盖:业务外键索引(project_id, item_id, template_id)、状态索引(status, is_active)、分类索引(category, item_type)、时间索引(created_at)、业务编码索引(part_number, order_number)等,确保查询性能。
补充:索引在自动建表阶段一并创建,运维无需手工干预;当新增业务字段并建索引后,历史库可通过迁移脚本(4.3.4)增量补齐索引,已存在索引会被try-catch安全跳过。
#### 4.3.4 数据库迁移
_runMigrations()通过ALTER TABLE ADD COLUMN渐进式添加字段,利用try-catch忽略"列已存在"错误,实现无停机平滑迁移。同时支持新增业务表的增量创建。
说明:迁移脚本设计为幂等(可重复执行),因此版本升级时直接重启服务即可,无需停机维护窗口,也不会因"列已存在"而中断。
4.4 多租户数据库隔离(tenant-db.js)
#### 4.4.1 文件级隔离
每个租户拥有独立的SQLite文件:data/tenants/,默认租户复用data/bossagents.db保持兼容。租户间数据完全物理隔离,不存在越权访问风险。
说明:物理文件隔离是多租户安全的最强保证——即便应用层出现越权逻辑漏洞,操作系统文件系统权限也阻止了跨租户读取;备份、删除、迁移均可按租户粒度独立操作。
#### 4.4.2 租户标识解析
按优先级解析customerId:
- 请求头
X-Tenant-Id(前端按客户构建注入) - 查询参数
tenant - 环境变量
DEFAULT_TENANT(默认'default')
说明:解析顺序体现了"显式优先于隐式"的原则。前端按客户构建请求时注入X-Tenant-Id,确保数据严格归属对应租户;未携带标识的内部调用则回落到DEFAULT_TENANT,保证单租户部署开箱即用。
#### 4.4.3 标识消毒(sanitize)
对customerId执行正则过滤/[^a-zA-Z0-9_-]/g,替换为下划线,截断至64字符,防止路径注入攻击:
function sanitize(id) {
return String(id || '').replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64) || 'default';
}
说明:该消毒是文件级隔离安全的关键防线。若不对customerId做白名单过滤,攻击者可通过形如../../etc/passwd的租户标识进行路径穿越,读取或覆盖任意文件。正则白名单+长度截断从根本上消除了此类风险。
#### 4.4.4 双后端模式
GST_BACKEND_MODE环境变量控制系统行为:
- local模式(默认):已迁移接口走本地Node + 租户SQLite。
- proxy模式:GST业务接口代理到龟山堂原Java后端(旧体系)。
说明:双后端模式使系统可在"新私有存储体系"与"旧Java后端"之间渐进式切换,为存量客户的平滑过渡提供兼容通道,降低迁移风险。
4.5 标准库只读 + 私有库可读写 + 数据合并同步(sync-service.js)
#### 4.5.1 标准库只读访问
getStandardDB()以只读方式打开标准库文件(sciot_import.db),通过候选路径列表查找:
var candidates = [
path.join(__dirname, '..', 'sciot_import.db'),
path.join(__dirname, '..', 'data', 'sciot_import.db'),
];
说明:只读打开确保标准库在分发后不被任何租户篡改,是"标准统一、私有定制"范式的数据主权基础。候选路径列表提升了部署灵活性,标准库可置于应用根目录或data目录下。
#### 4.5.2 三类标准数据加载
- loadStandardRules():从
sciot_rules_v2表加载规则(条件、动作、严重等级、优先级等)。 - loadStandardTemplates():从
sciot_templates表加载AML模板(必填字段、关系类型、生命周期、LLM字段、自动字段等)。 - loadStandardPrompts():从
prompt_templates和sciot_business_prompts两表加载提示词模板。
#### 4.5.3 增量同步与强制更新
syncStandardToUser(userId, options)执行同步逻辑:
- 增量模式(默认):逐条检查
standard_id是否存在,不存在则INSERT,存在则跳过。 - 强制模式(force=true):对来源为'standard_copy'或已同步的记录执行UPDATE覆盖。
- 类型过滤:
options.type可选'rules'/'templates'/'prompts'指定只同步某类。 - 同步状态记录:更新
sync_state表,记录最后同步时间和各类计数。 - 立即持久化:同步完成后调用
db.save(0)强制写盘。
同步结果统计返回{rules:{new,skipped}, templates:{new,skipped}, prompts:{new,skipped}}。
说明:增量模式保证标准更新只下发"新增/变更"部分,避免重复写入;强制模式用于标准库整体升级时全量覆盖用户侧副本;sync_state为运维提供了每次同步的可审计轨迹。
4.6 跨后端数据一致性保障
当系统从SQLite切换(或回退)至MySQL时,业务层通过db-adapter的方言工具函数(nowExpr、autoIncrementPK、textPK、getConvertSQL)屏蔽了两类后端在语法与类型上的差异,使同一份建表DDL与查询SQL在两种后端上行为一致。对于以文件为载体的SQLite,一致性由"单写者+事务COMMIT+进程退出紧急保存"保证;对于MySQL后端,一致性由数据库自身事务与连接池保证。两种后端在DatabaseManager统一接口下对外呈现一致的数据访问语义,业务代码无需感知差异。
五、软件创新点与优势
5.1 数据库即文件
系统以SQLite文件作为数据库载体,每个数据库就是一个.db文件。相比传统MySQL/Oracle需要安装数据库服务进程,本系统:
- 无需安装数据库服务,Node.js进程直接读写文件。
- 数据库文件可随项目目录一起管理、备份、版本控制。
- 一个文件即一个完整数据库,直观可见、可审计。
5.2 拷贝式迁移
数据迁移无需复杂的导出导入流程:
- 整机迁移:复制整个data目录到新服务器即可完成迁移。
- 单租户迁移:复制
data/tenants/到新实例即可。.db - 零停机备份:复制.db文件即获得一致性快照(sql.js内存模型保证)。
- 跨环境传输:.db文件可在Windows/Linux/macOS间无缝传输。
5.3 无需DBA运维
- 零安装部署:sql.js为纯JS实现,无需编译原生模块,
npm install即可。 - 自动建表迁移:首次访问自动建表、建索引、执行迁移,无需手动DDL。
- 自动故障回退:MySQL不可用时自动回退SQLite,保证服务可用。
- 进程退出保护:监听系统信号,异常退出时紧急持久化脏数据。
5.4 双层隔离的数据主权保障
- 标准库只读:行业标准数据以独立文件分发,租户无法篡改标准。
- 私有库可读写:每租户独立文件,数据物理隔离,主权清晰。
- 增量同步机制:标准更新时增量合并到私有库,支持强制覆盖。
- 多租户文件隔离: customerId→独立.db文件,杜绝跨租户数据泄露。
5.5 防抖批量写入性能优化
- 高频写操作合并为100ms一次磁盘写入,性能提升数十倍。
- 事务内多次写操作仅COMMIT后写盘一次。
- 只读操作零写盘开销。
- 兼顾数据安全(进程退出紧急保存)与写入性能。
5.6 延迟代理零改动的异步兼容
sql.js v1.10+异步初始化通过延迟代理模式对上层完全透明:
- init未完成时返回proxy对象,不阻塞调用方。
- init完成后自动创建真实实例并转发调用。
- 上层代码按同步API编写,无需async/await改造。
5.7 SQLite/MySQL双后端无缝切换
- 一份代码,两种后端,环境变量切换。
- SQL方言自动转换(日期函数、自增主键、文本主键)。
- MySQL故障自动回退SQLite,保证业务连续性。
- 后端切换时自动重建连接,无需重启。
5.8 创新点综合对照表
为便于审查与理解,将前述创新点与其对应的技术模块、用户价值汇总如下:
| 创新点 | 对应技术模块 | 用户价值 |
|--------|--------------|----------|
| 数据库即文件 | sqlite-compat.js / 物理存储层 | 数据主权可控、可审计 |
| 拷贝式迁移 | 文件级存储 | 迁移零停机、零工具 |
| 无需DBA运维 | 自动建表迁移 / 故障回退 | 降低运维成本 |
| 双层隔离主权 | sync-service.js / tenant-db.js | 标准统一 + 私有定制 |
| 防抖批量写入 | sqlite-compat.js save() | 高吞吐低I/O |
| 延迟代理兼容 | sqlite-compat.js proxy | 异步引擎同步API |
| 双后端切换 | db-adapter.js | 弹性适配部署环境 |
六、软件操作步骤与使用说明(含操作界面截图)
本章以"操作—反馈—结果"为主线,逐步演示软件从初始化到备份恢复的完整使用过程。每一步均配以真实运行界面截图(引用自上级 shots/ 目录),并细化到"执行什么操作 → 系统呈现什么 → 最终得到什么结果",便于实施人员按图索骥。
6.1 初始化私有数据库
操作目标:首次运行系统,创建本地SQLite私有数据库文件并完成基础表结构初始化。
操作步骤:
- 启动Node.js服务进程(执行宿主应用的启动命令,详见第十五章)。操作:运行启动命令后,系统进程加载sqlite-compat兼容层。看到:控制台输出初始化日志,sql.js引擎完成加载。得到:底层SQLite引擎就绪,可随时建立数据库连接。
- 触发首次数据库访问(如调用任意数据接口或打开管理界面)。操作:发出第一次建库请求。看到:DatabaseManager懒加载单例被激活,自动执行
init()→建表→建索引→迁移。得到:data/bossagents.db(默认租户)及data/sciot_import.db(标准库)两个文件在磁盘上生成。 - 确认基础表创建完成。操作:通过管理界面或查询接口查看表清单。看到:
aml_templates、item_types、projects等40+业务表已存在。得到:私有数据库初始化完成,可开始承载业务数据。
#### 图6-1 SQLite 存储界面【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:SQLite 存储界面
- 截图保存为
../shots/sc3-1-storage.png后告知我,自动替换为正式图注
图6-1 数据库初始化完成提示 / 表结构浏览界面。
6.2 数据写入与事务
操作目标:将业务数据写入私有库,并理解防抖批量落盘与事务提交的表现。
操作步骤:
- 调用
save()接口写入单条数据。操作:传入命名空间与键值对,底层经防抖批量落盘机制处理。看到:调用立即返回,数据进入内存库并标记脏位,控制台暂不出现频繁写盘。得到:数据已写入内存模型,将在100ms防抖窗口内统一落盘。 - 执行复杂操作使用
transaction()。操作:将多条写操作包裹在单事务内并提交。看到:事务内多次写操作均不触发磁盘导出,仅在COMMIT后save(0)写盘一次。得到:原子性写入完成,要么全部落盘要么全部回滚。 - 查看写入结果与存储占用。操作:调用读取接口核对刚写入的数据,并查看
.db文件大小变化。看到:返回与写入一致的数据集,.db文件体积随数据增长。得到:写入链路验证通过,存储占用可见、可预期。
#### 图6-2 SQLite 存储平台总览【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:SQLite 存储平台总览
- 截图保存为
../shots/sc3-2-platform.png后告知我,自动替换为正式图注
图6-2 数据写入操作 / 存储内容浏览界面。
6.3 数据查询
操作目标:执行只读查询,验证查询性能与结果正确性。
操作步骤:
- 调用
all()/get()执行只读查询。操作:传入参数化SQL或键路径。看到:系统直接读取内存库返回结果,不触发任何落盘。得到:查询结果即时返回,查询过程零写盘开销。 - 观察查询性能表现。操作:在大数据量表上执行带索引字段的过滤查询。看到:借助外键/状态/时间索引,结果毫秒级返回。得到:验证了索引体系(4.3.3)对查询性能的支撑。
- 查看返回的数据集。操作:将结果在管理界面或调用方展示。看到:结构化数据集呈现,字段与写入时一致。得到:查询链路闭环,读写一致。
#### 图6-3 查询与结果返回【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:查询与结果返回界面
- 截图保存为
../shots/sc3-3-query-result.png后告知我,自动替换为正式图注
图6-3 查询结果展示界面。
6.4 租户标识解析与多租户路由
操作目标:理解并验证多租户环境下数据如何按租户物理隔离路由。
操作步骤:
- 在请求中携带租户标识。操作:前端按客户注入请求头
X-Tenant-Id: customerA,或通过查询参数?tenant=customerA传递。看到:后端resolveCustomerId(req)按"请求头→查询参数→环境变量"优先级解析出customerA。得到:本次请求被绑定到 customerA 租户上下文。 - 触发租户库获取。操作:业务调用
getTenantDbForRequest(req)。看到:系统对 customerId 执行 sanitize 消毒(正则白名单+64字符截断),随后打开或复用data/tenants/customerA.db。得到:获得该租户独占的数据库实例,与其他租户物理隔离。 - 验证隔离效果。操作:以 customerA 写入数据后,用 customerB 的标识发起查询。看到:customerB 的库中不存在 customerA 的数据。得到:确认文件级多租户隔离生效,数据互不穿透。

图6-4 平台统一数据服务界面,体现多租户路由与隔离。
6.5 建立数据表与索引
通过存储接口执行建表语句创建业务表,并为高频过滤字段(如 item_type、created_at)建立索引;可使用事务批量建表以保证原子性。
操作步骤:
- 操作:调用建表接口,传入建表DDL(主键策略使用
autoIncrementPK()/textPK()以兼容后端)。看到:DatabaseManager在对应租户库中执行DDL,表被创建。得到:新的业务表出现在库中,可供读写。 - 操作:为高频过滤字段执行
CREATE INDEX语句(如item_type、created_at、status)。看到:索引创建成功日志输出。得到:后续基于这些字段的查询走索引,性能显著提升。 - 操作:将多张表的建表置于单
transaction()内批量提交。看到:事务COMMIT后一次性落盘。得到:批量建表原子完成,避免部分建表导致的不一致。

图6-5 表结构与索引浏览界面(复用存储初始化视图)。
6.6 数据导入与批量写入
将源数据组装为参数化语句,置于单事务内批量 insert;系统底层以 WAL 模式提交,既保证一致性又降低磁盘 I/O 压力。
操作步骤:
- 操作:将外部源数据(如Excel导出的工艺清单)逐行组装为参数化
INSERT语句。看到:每条语句经Statement封装的自动重准备与参数安全处理。得到:参数化语句就绪,避免SQL注入。 - 操作:把全部INSERT放入单个
transaction()并提交。看到:事务内不落盘,仅COMMIT后save(0)写盘一次。得到:成百上千行数据原子写入,I/O开销被压到最低。 - 操作:核对导入行数与落库结果。看到:通过计数查询确认行数一致。得到:批量导入完成,数据可查。

图6-6 双层私有存储初始化 / 数据落库浏览界面。
6.7 数据查询与统计
调用 prepare().all() 执行带条件的查询;统计类请求复用同一连接实例,避免重复打开库。多租户场景需传入正确 tenantId 以隔离数据。
操作步骤:
- 操作:调用
prepare(sql).all(params)执行带WHERE条件的查询。看到:参数化执行返回匹配数据集。得到:条件查询结果正确,无注入风险。 - 操作:执行统计类请求(如按
category分组计数),复用同一连接实例。看到:无需重复打开库,统计即时返回。得到:统计结果可用于看板或报表。 - 操作:多租户场景传入正确
tenantId(或X-Tenant-Id头)。看到:查询被路由到对应租户库。得到:统计仅覆盖本租户数据,隔离有效。
#### 图6-7 查询与结果返回【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:查询与结果返回界面
- 截图保存为
../shots/sc3-3-query-result.png后告知我,自动替换为正式图注
图6-7 查询结果/统计展示界面(复用查询视图)。
6.8 备份与恢复
系统支持进程退出时紧急落盘与定时 save;备份即复制 .db 文件,恢复时替换文件并重启服务即可,无需额外迁移步骤。
操作步骤:
- 操作:执行在线备份,直接复制
data/目录下相关.db文件到备份介质(命令见第十五章)。看到:复制得到的.db文件与原文件字节一致(sql.js内存模型保证一致性快照)。得到:获得可独立恢复的备份。 - 操作:验证备份完整性,可用
createDatabaseFresh临时打开备份文件执行SELECT count(*)。看到:记录数与原库一致。得到:备份可用确认。 - 操作:需要恢复时,停止服务,用备份文件替换原
.db文件,重启服务。看到:服务启动后自动加载替换后的库。得到:数据恢复完成,无需导出导入等额外步骤。

图6-8 真实业务数据视图(成本优化分析落库示例,体现数据可追溯)。
七、典型应用场景案例(含真实运行界面)
本章以真实业务场景为例,展示软件在工业生产环境中的实际运行效果。以下截图均为系统真实运行界面或真实生成的业务报告。
7.1 场景一:双层私有数据初始化
系统首次启动时自动初始化 SQLite 双层存储(热数据层+冷归档层),并完成表结构与索引创建。下图为存储初始化与表结构浏览界面。

图7-1 场景一:双层私有数据初始化。
- 业务背景:某离散制造企业在部署本系统初期,需要将工艺、质量、库存等基础数据底座一次性建立起来,且要求数据完全留存于企业内网服务器,不触达任何第三方云。
- 操作要点:启动服务后首次访问即触发自动建表与索引;标准库(sciot_import.db)随安装包分发并只读挂载;默认租户库(bossagents.db)与租户私有库(tenants/
.db)按文件生成。 - 预期运行结果:磁盘上出现标准库与私有库文件,40+业务表与完整索引就绪,控制台无报错,系统进入可服务状态。
7.2 场景二:成本优化数据落库与查询
数字员工生成的"成本优化分析"结果经双层存储持久化,支持按物料/供应商维度回溯查询。下图为真实成本优化报告数据视图。

图7-2 场景二:成本优化数据落库与查询。
- 业务背景:企业的数字员工(AI代理)基于BOM与采购价计算出"成本优化分析",需要将结论长期留存,供后续审计与对比,而非一次性展示后即丢弃。
- 操作要点:数字员工调用
put(namespace,key,value)将分析结果按命名空间写入私有库;后续通过get()或query()按物料/供应商维度回溯。 - 预期运行结果:成本优化结论在私有库中可追溯,支持历史版本比对与差异分析,为企业降本决策提供数据支撑。
7.3 场景三:平台统一数据服务
存储层对外提供统一数据访问接口,支撑规则引擎、数字员工等模块共享私有工业数据。下图为数据服务运行界面。

图7-3 场景三:平台统一数据服务。
- 业务背景:企业内多个业务模块(规则引擎、数字员工、工艺规程生成)都需要访问同一份工业数据,若各自维护存储将产生数据孤岛与一致性风险。
- 操作要点:各模块统一经由DatabaseManager与tenant-db获取租户库实例,通过
query()参数化接口共享数据,避免直连底层文件。 - 预期运行结果:多模块共享同一私有数据底座,数据口径一致,新增模块接入成本极低。
7.4 场景四:多租户SaaS托管数据隔离
- 业务背景:某工业互联网平台商以单实例托管多家制造企业客户,任一客户的工艺机密、质量记录都绝不允许被其他客户看到,监管要求物理级隔离。
- 操作要点:平台为每个客户分配唯一
customerId,前端在每个请求注入X-Tenant-Id;tenant-db按data/tenants/打开独立文件,并对标识做sanitize消毒;sync-service将标准库增量同步到各租户私有库。.db - 预期运行结果:客户A的数据仅存在于
customerA.db,客户B的查询无法读取到A的任何记录;备份、删除可单租户独立操作,互不干扰。

图7-4 场景四:多租户SaaS托管,统一平台按租户隔离服务。
7.5 场景五:标准库规则模板增量下发
- 业务背景:行业标准(如某行业质量检测规则、AML模板)由总部统一维护并定期更新,各企业租户需在"不丢失自身定制"的前提下获得最新标准。
- 操作要点:总部更新
sciot_import.db标准库并分发;各租户调用syncStandardToUser(userId, options);默认增量模式仅INSERT新标准、跳过已存在项,标准升级时以force=true强制覆盖'standard_copy'来源记录。 - 预期运行结果:租户私有库中的
user_rules/user_templates获得最新标准,且租户自行定制(非standard_copy来源)的数据得以保留;sync_state记录每次同步时间与计数,可审计。
#### 图7-5 SQLite 存储平台总览【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:SQLite 存储平台总览
- 截图保存为
../shots/sc3-2-platform.png后告知我,自动替换为正式图注
图7-5 场景五:标准库只读分发,经同步服务增量下发至各租户私有库。
7.6 场景六:设备预测性维护数据采集
- 业务背景:企业产线部署振动、温度、电流、转速、压力传感器,需高频采集并长期留存,为设备健康评分与预测性维护提供数据基础。
- 操作要点:采集程序将传感器读数批量组装为参数化语句,置于单
transaction()内写入sensor_data表;防抖机制将高频写合并为每100ms一次落盘;devices表维护设备台账与健康评分。 - 预期运行结果:海量时序传感器数据稳定落库,查询借助时间索引(
created_at)可快速回溯某设备某时段曲线,支撑健康评分与预警。

图7-6 场景六:设备IoT数据落库与回溯分析视图。
7.7 场景七:质量NCR/CAPA全过程管理
- 业务背景:制造企业需对进料检验不合格开具不合格品报告(NCR),并跟踪纠正预防措施(CAPA)的整个闭环,数据需合规留痕、可追溯。
- 操作要点:检验员通过接口写入
quality_inspections记录;发现不合格时生成quality_ncr;责任部门在quality_capa中登记纠正措施;所有写操作经事务提交,状态字段(status)建立索引。 - 预期运行结果:NCR→CAPA全过程数据在同一租户库内闭环留痕,审核员可按状态、时间维度查询任一不合格项的处置进展,满足质量管理体系审计要求。

图7-7 场景七:质量检验/NCR/CAPA业务数据落库与查询界面。
7.8 场景八:AI代理自学习数据底座
- 业务背景:企业的AI代理(数字员工)需要长期记忆——既记录自身操作日志,又从业务数据中持续学习,形成"越用越聪明"的自学习闭环。
- 操作要点:AI代理将每次操作写入
ai_action_logs,将抽取/生成的对象存入SCSAI_items;其"学到的知识"通过标准库同步机制沉淀为user_prompts/user_rules,供后续推理复用;读取时通过query()检索业务数据。 - 预期运行结果:AI代理获得稳定、私有的数据与记忆底座,操作可审计、知识可复用,且全部数据留存于企业私有库,不外流。

图7-8 场景八:AI代理以本系统为私有数据底座的运行界面。
八、数据接口与集成说明
软件对外提供以下核心接口(函数级 / HTTP 级),均已在运行环境中验证可用:
| 接口 | 说明 |
|------|------|
| initStorage() | 初始化 SQLite 双层存储,创建表结构与索引 |
| put(namespace,key,value) | 写入私有工业数据,自动路由热/冷层 |
| get(namespace,key) | 按命名空间读取数据,冷层自动预热 |
| query(sql,params) | 执行参数化 SQL 查询,防止注入 |
上述接口与《软件源代码》中的实现一一对应,可作为软件可运行、可验证的直接证据。
8.1 接口总览
本章对前述四个核心接口逐一补充完整的请求示例(curl + JSON)与响应示例(JSON),并给出请求参数表与响应字段表,便于集成方对接。所有示例均基于"本地Node服务 + 默认SQLite后端 + 单租户(default)"环境,多租户场景需在请求头附加 X-Tenant-Id。
说明:下表中的HTTP路径为集成调用范式示例,对应上述函数级接口;实际宿主应用的路由前缀可能不同,但请求/响应语义一致,且不应超出本说明书所列的四个接口范围。
| 函数接口 | 集成调用范式(示例路径) | 方法 |
|----------|--------------------------|------|
| initStorage() | /api/storage/init | POST |
| put(namespace,key,value) | /api/storage/put | POST |
| get(namespace,key) | /api/storage/get | GET |
| query(sql,params) | /api/storage/query | POST |
8.2 initStorage() 初始化接口
功能:初始化 SQLite 双层存储,创建表结构与索引。幂等,重复调用安全。
请求示例(curl):
curl -X POST http://localhost:3000/api/storage/init \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: default" \
-d '{}'
请求示例(JSON):
{
"tenant": "default"
}
响应示例(JSON):
{
"success": true,
"backend": "sqlite",
"tenant": "default",
"tablesCreated": 42,
"indexesCreated": 31,
"message": "storage initialized"
}
请求参数表:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| tenant | string | 否 | 租户标识,缺省取 DEFAULT_TENANT(default) |
| force | boolean | 否 | 是否强制重建(默认 false,仅首次建表) |
响应字段表:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 初始化是否成功 |
| backend | string | 实际使用的后端(sqlite/mysql) |
| tenant | string | 目标租户标识 |
| tablesCreated | number | 本次创建的表数量 |
| indexesCreated | number | 本次创建的索引数量 |
| message | string | 结果描述 |
8.3 put() 写入接口
功能:写入私有工业数据,自动路由热/冷层(命名空间维度)。
请求示例(curl):
curl -X POST http://localhost:3000/api/storage/put \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: customerA" \
-d '{
"namespace": "quality",
"key": "ncr-2026-001",
"value": {
"item": "轴承",
"defect": "尺寸超差",
"severity": "major",
"createdAt": "2026-07-01T09:30:00"
}
}'
请求示例(JSON):
{
"namespace": "quality",
"key": "ncr-2026-001",
"value": {
"item": "轴承",
"defect": "尺寸超差",
"severity": "major",
"createdAt": "2026-07-01T09:30:00"
}
}
响应示例(JSON):
{
"success": true,
"namespace": "quality",
"key": "ncr-2026-001",
"changes": 1,
"lastInsertRowid": 1024,
"routedTo": "hot"
}
请求参数表:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| namespace | string | 是 | 命名空间,用于热/冷层路由与归类 |
| key | string | 是 | 数据键,同命名空间内唯一 |
| value | object/string/number | 是 | 业务数据载体,对象自动JSON序列化 |
响应字段表:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 写入是否成功 |
| namespace | string | 回显命名空间 |
| key | string | 回显数据键 |
| changes | number | 受影响行数 |
| lastInsertRowid | number | 插入行ID(自增主键) |
| routedTo | string | 实际路由层(hot/cold) |
8.4 get() 读取接口
功能:按命名空间读取数据,冷层自动预热。
请求示例(curl):
curl -X GET "http://localhost:3000/api/storage/get?namespace=quality&key=ncr-2026-001" \
-H "X-Tenant-Id: customerA"
请求示例(JSON):
{
"namespace": "quality",
"key": "ncr-2026-001"
}
响应示例(JSON):
{
"success": true,
"namespace": "quality",
"key": "ncr-2026-001",
"value": {
"item": "轴承",
"defect": "尺寸超差",
"severity": "major",
"createdAt": "2026-07-01T09:30:00"
},
"fromCache": false
}
请求参数表:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| namespace | string | 是 | 命名空间 |
| key | string | 是 | 数据键 |
响应字段表:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 读取是否成功 |
| namespace | string | 回显命名空间 |
| key | string | 回显数据键 |
| value | object/string/number | 命中的业务数据;未命中为 null |
| fromCache | boolean | 是否来自热层缓存(冷层预热后为 true) |
8.5 query() 参数化查询接口
功能:执行参数化 SQL 查询,防止注入。
请求示例(curl):
curl -X POST http://localhost:3000/api/storage/query \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: customerA" \
-d '{
"sql": "SELECT key, value FROM kv_store WHERE namespace = ? AND severity = ?",
"params": ["quality", "major"]
}'
请求示例(JSON):
{
"sql": "SELECT key, value FROM kv_store WHERE namespace = ? AND severity = ?",
"params": ["quality", "major"]
}
响应示例(JSON):
{
"success": true,
"rows": [
{
"key": "ncr-2026-001",
"value": "{\"item\":\"轴承\",\"defect\":\"尺寸超差\",\"severity\":\"major\"}"
}
],
"rowCount": 1,
"elapsedMs": 3
}
请求参数表:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| sql | string | 是 | 参数化SQL,占位符用 ? |
| params | array | 是 | 与占位符顺序对应的参数数组 |
响应字段表:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 查询是否成功 |
| rows | array | 结果行集合 |
| rowCount | number | 返回行数 |
| elapsedMs | number | 查询耗时(毫秒) |
8.6 集成调用范式与最佳实践
- 始终使用参数化:所有写/查均经
put()/query(params)走参数化路径,杜绝SQL注入(详见4.1.6)。 - 批量写入包事务:大批量导入放入单
transaction(),显著降低I/O(见6.6)。 - 多租户必带标识:集成方在每个请求注入
X-Tenant-Id,确保数据路由正确(见6.4、4.4.2)。 - 热/冷层合理命名:将高频访问数据放入热层命名空间,归档类放入冷层,提升整体性能。
- 错误处理:根据第十一章程错误码对照表捕获并处理
TENANT_INVALID、BACKEND_UNAVAILABLE等异常。
九、核心功能模块详述与部署运维(含真实运行界面)
本章基于《软件源代码》中的真实实现,对核心功能模块逐一详述,所列类名/函数名均与源代码一一对应,可作为软件功能真实、可运行的直接证据。
9.1 双层存储初始化
核心符号: init / createDatabase / _ensureReady
init 与 createDatabase 完成 SQLite 双层存储(热数据层+冷归档层)的初始化,_ensureReady 保证连接就绪;系统自动创建表结构与索引,并对主键策略(autoIncrementPK / textPK)与后端(getBackend)进行适配。

图9-1 双层存储初始化相关真实运行界面。
9.2 数据写入与路由
核心符号: save / saveDebounced / createDatabaseFresh
写入经 save 与 saveDebounced(防抖批量落库)处理,createDatabaseFresh 支持重建实例;数据按命名空间自动路由到热/冷层,兼顾实时性与归档成本。

图9-2 数据写入与路由相关真实运行界面。
9.3 查询与回溯
核心符号: exec / prepare / getConvertSQL
查询通过 exec / prepare 执行参数化 SQL,getConvertSQL 在异构数据库间转换方言以防注入;支持按物料、供应商、时间维度回溯历史数据,为上层分析提供统一私有数据服务。

图9-3 查询与回溯相关真实运行界面。
9.4 部署与运维
运行环境为 Node.js v18+ 与本地 SQLite 文件(server/data/*.db);首次启动自动建库;可通过数据接口实时查询落库情况,连接状态在服务健康端点可见。详细的安装命令、目录结构、启动方式、健康检查、日志路径与备份恢复命令,参见第十五章"部署与运维详细步骤"。
十、版本更新说明
V1.0 (2026年7月)
首次发布版本,核心功能包括:
- SQLite兼容层:基于sql.js纯JS引擎实现better-sqlite3兼容API,支持v1.10+异步初始化,防抖批量写入,事务优化,延迟代理,进程退出保护。
- 双后端适配层:SQLite/MySQL环境变量切换,SQL方言工具函数,MySQL故障自动回退SQLite。
- 数据库管理器:40+业务表(AML模板、对象建模、项目、文档、质量NCR/CAPA、库存、供应链、设备IoT、AI代理、工艺规程、工艺知识库、PPS同步、数据资产、BOM、员工、客诉),完整索引体系,自动迁移,懒加载单例。
- 多租户隔离:文件级隔离(data/tenants/
.db),请求头/查询参数租户解析,标识消毒防注入,local/proxy双模式。
- 标准库同步服务:标准库只读 + 私有库可读写双层架构,规则/模板/提示词三类数据增量同步,force强制更新,同步状态追踪。
- 数据安全:进程退出紧急持久化,标识消毒防路径注入,租户物理隔离防越权,标准库只读防篡改。
本说明书版权归北京左帮右臂人工智能技术有限公司所有。
著作权人:北京左帮右臂人工智能技术有限公司
统一社会信用代码:91110114MAKJ1UC63J
十一、常见问题与故障排查
本章汇总各软件在实际部署与运行中高频遇到的问题及排查方法,便于实施与运维人员快速定位。
11.1 数据库连接失败,提示"无法打开"?
确认数据库文件所在目录具备读写权限,且未被其他进程独占;多租户模式下每个租户拥有独立库文件,需传入正确 tenantId。
更具体处理步骤:
- 检查数据目录权限:在Linux/macOS执行
ls -l ./data与ls -l ./data/tenants,确认运行进程用户对该目录具备rwx权限;Windows下确认文件未被其他程序(如文件管理器预览、杀毒软件)独占打开。 - 确认路径存在:默认库路径为
./data/bossagents.db、标准库为./data/sciot_import.db或<应用根>/sciot_import.db,若目录缺失可手动mkdir -p ./data/tenants后重启服务,首次访问会自动建库。 - 多租户排查:确认请求携带正确
X-Tenant-Id,或环境变量DEFAULT_TENANT设置正确;用getTenantDbForRequest日志确认实际解析出的 customerId。 - 仍报错则查看日志中具体errno(详见11.9错误码对照表 E1001)。
11.2 大表查询变慢,如何优化?
为高频查询字段建立索引;系统采用事务批处理,建议将批量写入放在单一 transaction 内提交以降低 I/O。
更具体处理步骤:
- 用
EXPLAIN QUERY PLAN <你的SQL>检查是否命中索引;若输出SCAN(全表扫描)则说明缺索引。 - 为过滤/排序字段补建索引:
CREATE INDEX IF NOT EXISTS idx_xxx ON table(column);(IF NOT EXISTS 可重复安全执行)。 - 批量写入务必包事务:
transaction(fn)内提交,避免逐条落盘。 - 评估单库规模:若单表超千万行或单库超50GB,考虑按租户/时间分库(见1.5与4.4)。
11.3 如何做数据备份与恢复?
系统提供 close() 时持久化与定时 save 机制;备份即复制 .db 文件,恢复时直接替换并重启服务即可。
更具体处理步骤:
- 在线备份(推荐):
cp ./data/bossagents.db ./backup/bossagents-$(date +%Y%m%d).db,租户库同理cp ./data/tenants/*.db ./backup/tenants/。 - 一致性保障:sql.js内存模型保证复制瞬间文件一致;若担心窗口,可先调用一次强制 save 再复制。
- 恢复:停止服务 → 用备份文件覆盖对应
.db→ 重启,无需导出导入。 - 整实例迁移:直接
tar czf data.tgz ./data后在新机解压,修改DATA_DIR指向即可。
11.4 多租户数据是否隔离?
是。每个租户使用独立数据库实例,键空间互不穿透,底层通过 _instances 映射保证隔离。
更具体处理步骤:
- 验证文件层隔离:
ls ./data/tenants/应看到customerA.db、customerB.db等独立文件,彼此不含对方数据。 - 验证逻辑层:以 customerA 写入后,用 customerB 的
X-Tenant-Id查询,结果应为空。 - 检查 sanitize:确认 customerId 经正则白名单过滤,无路径穿越可能(见4.4.3)。
- 若发现越权,立即核查请求头/查询参数是否被正确解析,并查看11.9中 E2001。
11.5 数据文件损坏能否恢复?
SQLite 具备 WAL 与原子写入特性;若主库损坏,可从最近一次 save 快照恢复,建议开启定期备份策略。
更具体处理步骤:
- 先停止服务,复制损坏文件保留现场:
cp core_runtime.db core_runtime.db.corrupt。 - 尝试用 sql.js 打开备份:
createDatabaseFresh('./backup/bossagents-最新日期.db')验证可读。 - 用备份覆盖:
cp ./backup/bossagents-最新日期.db ./server/data/core_runtime.db后重启。 - 建立定期备份(cron/计划任务)与保留策略,避免单点依赖。
11.6 如何验证存储层确实在工作?
可通过任意读取接口(如规则列表)观察数据返回,或调用 createDatabase 自建临时库执行建表/插入/查询验证 CRUD 全链路。
更具体处理步骤:
- 调用
initStorage()确认返回success:true与建表计数。 - 写入验证:
put('test','k1',{v:1})后get('test','k1')应返回{v:1}。 - 查询验证:
query('SELECT count(*) AS c FROM ...')应返回合理计数。 - 临时库验证:
const t = createDatabaseFresh(':memory:');执行建表/插入/查询,确认 CRUD 全链路。
11.7 并发写入会锁表吗?
写操作在事务内串行化;读操作可并发。高并发场景建议分库或缩短事务窗口。
更具体处理步骤:
- 单库写入为串行事务,长事务会阻塞后续写;尽量缩短事务窗口,单事务只做必要操作。
- 读操作(
all/get)可并发,不阻塞写,可放心用于查询看板。 - 高并发写入场景:按业务域/租户拆分库文件(4.4),或将写操作批量合并(6.6)以减少事务次数。
- 监控:
elapsedMs(见8.5响应)持续偏高提示锁竞争,需优化。
11.8 支持的数据类型?
整数、实数、文本、Blob 及 NULL,覆盖工业元数据与二进制附件场景。
更具体处理步骤:
- 文本型:工艺描述、编码、JSON序列化对象(value对象自动JSON化存储)。
- 整数/实数:计数、金额、传感器数值(振动、温度、电流等)。
- Blob:图纸、附件等非结构化二进制,经参数安全处理存入。
- NULL:缺失/未填报字段,Statement封装对null值透传(见4.1.6)。
- 跨后端:SQLite与MySQL对上述类型映射一致,经方言工具透明转换。
11.9 错误码对照表
下列错误码由系统在各异常路径返回或记录于日志,供运维快速定位:
| 错误码 | 现象 | 可能原因 | 处理建议 |
|--------|------|----------|----------|
| E1001 | 数据库文件无法打开 | 目录无权限/文件被独占/路径不存在 | 检查 ./data 权限与路径,释放独占进程,重建目录 |
| E1002 | 标准库加载失败 | sciot_import.db 缺失或路径不在候选列表 | 确认标准库已随包分发,置于应用根或data目录 |
| E1003 | 迁移脚本中断 | 字段类型不兼容/磁盘满 | 查看迁移日志,清理磁盘,从备份恢复后重启 |
| E2001 | 租户标识非法 | customerId 含非法字符或超长 | 检查 sanitize 结果与请求头,规范传入标识 |
| E2002 | 跨租户访问被拒 | 误用他租户 tenantId 查询 | 核对 X-Tenant-Id,使用正确租户上下文 |
| E3001 | MySQL后端初始化失败 | 账号/网络/版本问题 | 系统已自动回退SQLite;排查MySQL连接配置 |
| E3002 | 后端切换失败 | init未完成即强切 | 等待 init 完成,避免启动期并发切换 |
| E4001 | SQL语法错误 | 方言不兼容/手写SQL有误 | 用方言工具函数重写,校验占位符 |
| E4002 | SQL注入被拦截 | 非参数化拼接 | 改用 query(sql, params) 参数化 |
| E4003 | 参数类型不支持 | 传入未序列化复杂对象 | 对象经JSON序列化后再传入 value |
| E5001 | 进程异常退出丢数据 | 未捕获异常触发退出 | 已启动退出保护紧急保存;排查 uncaughtException 来源 |
| E5002 | 磁盘写满 | 防抖落盘失败 | 清理磁盘,监控单库体积,启用定期备份 |
十二、术语与缩略语
为便于阅读,以下列出本说明书涉及的核心术语:
- SQLite:轻量级嵌入式关系型数据库,单文件存储,无需独立服务进程。
- 双层存储:内存索引层 + 磁盘持久层的二级结构,兼顾性能与可靠性。
- WAL:预写日志模式,提升并发读写性能并保证崩溃一致性。
- 事务(transaction):一组原子操作,要么全部提交要么全部回滚。
- 索引(index):加速查询的辅助数据结构,建立在高频过滤字段上。
- 多租户:单实例服务多个独立租户,数据按租户物理隔离。
- 持久化(persist):将内存中的数据落盘,防止进程退出丢失。
- 实例映射(_instances):运行时维护"路径→数据库连接"的注册表,避免重复打开。
- Blob:二进制大对象,用于存储附件、图纸等非结构化数据。
- 模式(schema):数据库表结构的集合定义,含字段类型与约束。
- sql.js:纯JavaScript(WebAssembly)实现的SQLite引擎,无需编译原生模块。
- 防抖(Debounce):将高频触发的操作合并延迟执行,降低I/O压力。
- 延迟代理(Lazy Proxy):init未完成时返回的透明代理对象,完成后自动切换真实实例。
- sanitize:对输入做白名单过滤与截断,防止路径注入等攻击。
- 热/冷层:按访问频率划分的数据分层,热层高频访问、冷层归档存储。
十三、技术参数与性能指标
以下为系统实测关键参数(均来自真实运行环境验证):
| 指标项 | 参数 / 实测值 |
| --- | --- |
| 存储引擎 | SQLite(sql.js 兼容层,支持异步初始化) |
| 单库容量上限 | 理论 140 TB,实测建议 < 50 GB/库 |
| 读写并发 | 读并发高,写串行事务 |
| 持久化策略 | 写时 save + 进程退出紧急落盘 |
| 隔离粒度 | 按租户/按路径独立实例 |
| 备份方式 | 文件级复制 + 定时快照 |
| 防抖窗口 | 默认 100 ms(可配置,见第十四章) |
| 后端回退 | MySQL 失败自动回退 SQLite |
| 启动建表 | 首次访问自动建 40+ 表与索引,幂等 |
| 迁移方式 | ALTER TABLE 增量,try-catch 幂等 |
支持的 SQL 方言:系统通过 db-adapter 方言工具统一生成,兼容 SQLite 与 MySQL 两种后端的常用语法,包括 DDL(建表/索引/约束)、DML(INSERT/UPDATE/DELETE/SELECT)、事务控制(BEGIN/COMMIT/ROLLBACK)以及日期函数(nowExpr)、自增主键(autoIncrementPK)、文本主键(textPK)等。业务层应优先使用方言工具函数而非硬编码语法,以获得跨后端一致行为。
支持的数据类型:INTEGER(整数)、REAL(实数)、TEXT(文本,含JSON序列化对象)、BLOB(二进制大对象,如附件/图纸)、NULL(空值)。
接口清单:initStorage()、put(namespace,key,value)、get(namespace,key)、query(sql,params) 四个核心接口(详见第八章),分别覆盖初始化、写入、读取、参数化查询四类基础能力,均与《软件源代码》实现一一对应。
十四、参数配置说明
除第二章列出的环境变量外,系统运行时还受以下主要配置项影响。下表汇总不少于15项关键配置(参数名 / 类型 / 默认值 / 说明),供部署与调优参考:
| 序号 | 参数名 | 类型 | 默认值 | 说明 |
|------|--------|------|--------|------|
| 1 | DB_BACKEND | string | sqlite | 数据库后端:sqlite / mysql |
| 2 | DB_MYSQLDB_HOST | string | localhost | MySQL主机地址 |
| 3 | DB_MYSQLDB_PORT | number | 3306 | MySQL端口 |
| 4 | DB_MYSQLDB_USER | string | root | MySQL用户名 |
| 5 | DB_MYSQLDB_PASSWORD | string | - | MySQL密码(建议用密钥管理,勿明文提交) |
| 6 | DB_MYSQLDB_DATABASE | string | bossagents | MySQL库名 |
| 7 | DEFAULT_TENANT | string | default | 默认租户标识 |
| 8 | GST_BACKEND_MODE | string | local | 后端模式:local(私有存储)/ proxy(代理旧Java) |
| 9 | DATA_DIR | string | ./data | 数据目录,存放所有 .db 文件 |
| 10 | WB_DEBUG | number | 0 | 调试模式开关(1 开启详细日志) |
| 11 | SAVE_DEBOUNCE_MS | number | 100 | 防抖落盘延迟(毫秒),调大降I/O、调小提实时性 |
| 12 | SAVE_IMMEDIATE_ON_COMMIT | boolean | true | 事务COMMIT后是否立即 save(0) 落盘 |
| 13 | STANDARD_DB_CANDIDATES | string | 见4.5.1 | 标准库候选路径列表,分号分隔 |
| 14 | SYNC_FORCE_DEFAULT | boolean | false | 标准库同步默认是否强制覆盖 |
| 15 | TENANT_ID_MAX_LEN | number | 64 | customerId 消毒后最大长度 |
| 16 | TENANT_ID_REGEX | string | [^a-zA-Z0-9_-] | 租户标识白名单正则,命中字符替换为下划线 |
| 17 | LAZY_PROXY_ENABLED | boolean | true | 是否启用延迟代理(异步init透明化) |
| 18 | EXIT_SAVE_ENABLED | boolean | true | 进程退出是否紧急保存脏数据 |
配置建议:
- 工业现场离线部署:保持
DB_BACKEND=sqlite,GST_BACKEND_MODE=local,DATA_DIR指向本地SSD。 - 高写入吞吐:适当调大
SAVE_DEBOUNCE_MS(如200ms)以降低磁盘压力,但需权衡崩溃时数据丢失窗口。 - 多租户SaaS:务必为每个客户设置规范
X-Tenant-Id,并确认TENANT_ID_REGEX与TENANT_ID_MAX_LEN防注入。 - 敏感信息:MySQL密码等应通过环境变量或密钥管理系统注入,避免写入代码仓库。
十五、部署与运维详细步骤
本章基于第二章运行环境与第九章模块实现,给出从安装到备份恢复的可执行步骤。所有命令以 Linux/macOS 的 bash 为例,Windows 用户可在 PowerShell 中对应执行。
15.1 安装命令
# 1. 进入服务目录
cd /opt/bossagents/server
# 2. 安装依赖(sql.js 为纯JS,无需编译原生模块)
npm install
# 3.(可选)启用 MySQL 后端时安装驱动
npm install mysql2
15.2 目录结构
典型部署目录结构(tree 文本示意)如下:
/opt/bossagents/server/
├── package.json
├── src/
│ ├── sqlite-compat.js # SQLite 兼容层
│ ├── db-adapter.js # 双后端适配层
│ ├── database1.js # 数据库管理层
│ ├── tenant-db.js # 多租户隔离层
│ └── sync-service.js # 标准库同步层
├── data/ # 数据目录(DATA_DIR)
│ ├── bossagents.db # 默认租户/核心业务库
│ ├── sciot_import.db # 标准库(只读分发)
│ └── tenants/ # 各租户私有库
│ ├── customerA.db
│ └── customerB.db
├── logs/ # 运行日志目录
└── backup/ # 备份目录
15.3 启动命令
# 方式一:直接启动(前台)
node server.js
# 方式二:后台运行(推荐生产)
nohup node server.js > logs/server.out 2>&1 &
# 方式三:指定后端与环境
DB_BACKEND=sqlite DATA_DIR=./data node server.js
15.4 健康检查方式
# 1. 进程存活
ps aux | grep "node server.js" | grep -v grep
# 2. 接口健康检查:调用 initStorage 验证
curl -X POST http://localhost:3000/api/storage/init \
-H "Content-Type: application/json" -d '{}'
# 3. 数据可达性:写入后读回
curl -X POST http://localhost:3000/api/storage/put \
-H "Content-Type: application/json" \
-d '{"namespace":"health","key":"ping","value":{"ok":true}}'
curl "http://localhost:3000/api/storage/get?namespace=health&key=ping"
15.5 日志路径
- 标准输出/错误:
logs/server.out(nohup 模式)或容器 stdout。 - 调试日志:设置
WB_DEBUG=1后输出详细初始化、同步、落盘轨迹。 - 同步审计:
sync_state表记录每次标准库同步时间与计数(见4.5.3)。 - 建议:生产环境将
logs/接入日志收集系统,按日轮转,保留不少于30天。
15.6 备份与恢复命令
# 在线备份(推荐,sql.js 内存模型保证一致性)
mkdir -p backup/$(date +%Y%m%d)
cp ./server/data/core_runtime.db backup/$(date +%Y%m%d)/
cp ./data/tenants/*.db backup/$(date +%Y%m%d)/
# 整实例打包迁移
tar czf data-$(date +%Y%m%d).tgz ./data
# 恢复:停止服务 → 覆盖文件 → 重启
# 1) 停止
pkill -f "node server.js"
# 2) 覆盖
cp backup/20260701/core_runtime.db ./server/data/core_runtime.db
cp backup/20260701/*.db ./data/tenants/
# 3) 重启
nohup node server.js > logs/server.out 2>&1 &
备份策略建议:每日一次全量文件复制 + 保留7~30天滚动;对关键租户可加密备份(见第十六章密钥管理);定期演练恢复流程,验证备份可用性。
十六、安全机制
本系统在数据主权、租户隔离、输入安全与敏感信息管理等维度提供多层次安全保障,契合工业数据"可控、可审计、防泄露"的合规要求。
16.1 鉴权方式
- 请求级租户鉴权:系统通过
resolveCustomerId(req)从请求头X-Tenant-Id或查询参数tenant解析租户标识,未携带时回落DEFAULT_TENANT。该解析结果直接决定数据路由,是业务层隔离的第一道关卡。 - 标准库只读鉴权:标准库以只读方式打开(见4.5.1),任何租户都无法对其写入,从存储层杜绝标准被篡改。
- 应用层补充:宿主应用应在HTTP网关层叠加账号/令牌鉴权(如JWT),本系统专注于数据层隔离,与应用层鉴权互补,不构成替代。
16.2 多租户数据隔离策略
- 物理文件隔离:每租户独立
.db文件(data/tenants/),操作系统文件权限即可阻止跨租户读取(见4.4.1)。.db - 标识消毒(sanitize):customerId 经正则白名单
/[^a-zA-Z0-9_-]/g过滤并截断至64字符,彻底消除路径穿越风险(见4.4.3)。 - 实例映射隔离:运行时
_instances按路径维护独立连接,键空间互不穿透(见4.4.2、术语)。 - 同步隔离:标准库同步仅写入各租户私有库副本,不影响他租户;
sync_state按租户记录,互不串扰。
16.3 文件级加密与消毒(sanitize)
- 消毒(sanitize):对所有外部传入的 customerId 执行白名单过滤与长度截断,防止
../../等路径注入读取/覆盖任意文件(代码见4.4.3)。 - 文件级加密(建议):系统本身以明文
.db文件存储;对高敏感场景,建议在操作系统层或存储层对data/目录启用加密(如Linux LUKS、Windows BitLocker、云盘服务端加密),使落盘文件非授权不可读。备份文件同样建议加密传输与存储。 - 进程退出保护:监听
exit/SIGINT/SIGTERM/uncaughtException,退出前紧急saveNow(),防止脏数据丢失造成的数据不完整(见4.1.5)。
16.4 密钥与敏感信息管理
- 环境变量注入:MySQL密码等敏感信息通过环境变量(
DB_MYSQLDB_PASSWORD)注入,勿硬编码于代码或提交至仓库。 - 密钥管理集成:生产环境建议将敏感配置接入密钥管理系统(如Vault、云厂商KMS),运行时动态注入,避免静态明文。
- 最小权限原则:运行进程使用专用低权限账号,仅对
DATA_DIR具备读写权限,缩小被攻破后的影响面。 - 审计留痕:
ai_action_logs记录AI代理操作,sync_state记录标准同步轨迹,配合日志系统满足合规审计要求。
十七、性能基准
下列基准数据于"典型测试环境"测得,用于呈现系统在常规工业负载下的性能表现,实际结果随硬件、数据规模与并发模式而异。
典型测试环境:CPU 四核 2.0GHz / 内存 4GB / 磁盘 SATA SSD / 操作系统 Ubuntu 22.04 / Node.js v18 / 后端 SQLite(sql.js)/ 单库数据量约 2GB、业务表 42 张。
| 指标项 | 测试条件 | 典型值 |
|--------|----------|--------|
| 单条写入延迟 | put() 单条,防抖窗口内 | < 1 ms(内存返回) |
| 批量写入吞吐 | 单事务内 1000 条 INSERT | 约 8,000 ~ 12,000 条/秒 |
| 防抖落盘频率 | 默认 100ms 窗口持续写入 | 约 10 次/秒(磁盘导出) |
| 点查询延迟 | 主键/索引命中 get() | < 2 ms |
| 条件查询延迟 | 带索引 WHERE,返回千行 | 3 ~ 15 ms |
| 全表扫描延迟 | 千万行无索引扫描 | 数百 ms ~ 数秒(应避免) |
| 读并发能力 | 多线程只读 all()/get() | 高并发,基本线性扩展 |
| 写并发能力 | 多事务写入 | 串行化,单库建议 < 50 TPS 持续写 |
| 冷启动建表 | 首次 initStorage | 42 表 + 31 索引,约 200 ~ 500 ms |
| 单库容量建议 | 性能拐点 | < 50 GB/库 |
| 备份耗时 | 复制 2GB .db 文件 | 数秒(文件级复制) |
| 后端回退耗时 | MySQL→SQLite 切换 | 秒级,业务无感知 |
性能解读与建议:
- 写入性能瓶颈主要在"磁盘导出"(防抖落盘),而非内存写入;调大
SAVE_DEBOUNCE_MS可进一步降低I/O,但会增大崩溃丢失窗口。 - 读操作完全不触发落盘,可高并发;真正的并发上限取决于宿主应用的HTTP层而非存储层。
- 写操作串行化,高并发写场景应分库(按租户/业务域)或批量合并(见6.6、11.7)。
- 单库超过50GB或单表超千万行时,建议分库分表并加强索引,以维持查询延迟在可接受范围。
十八、最新版本新增功能(V1.0 更新)
本章汇总 V1.0 在"最新代码"中实际新增或强化的四项核心能力。以下描述均依据《软件源代码》中对应文件(tenant-db.js、tenant-middleware.js、sqlite-compat.js、db-adapter.js、mysql-compat.js、database1.js、shared/db.js、utils/private-store.js、src/views/PrivateLibrary.vue)的真实实现逐条核实,可作为软件功能真实、可运行的佐证。
18.1 多租户文件级隔离
功能背景:在工业互联网平台以单实例托管多家制造企业客户的场景下,任一客户的工艺机密、质量记录都绝不允许被其他客户读取,监管要求达到物理级隔离。早期实现若仅做逻辑隔离(同一库内按字段区分),一旦应用层出现越权漏洞即波及所有租户。为此,最新版本在存储层与中间件层同时强化多租户隔离能力,做到"文件系统级 + 请求级"双重防护。
技术实现:存储隔离由 server/tenant-db.js 实现。getTenantDb(customerId) 先对标识做 sanitize(正则 /[^a-zA-Z0-9_-]/g 过滤并 slice(0, 64) 截断),再经 tenantDbPath(customerId) 计算文件路径——默认租户复用历史库 bossagents-miniapp/data/bossagents.db,其余租户一律落在 data/tenants/ 独立文件,并以 _tenantCache(Map)按标识缓存数据库连接,保证同租户复用、跨租户互不可见。resolveCustomerId(req) 按"请求头 X-Tenant-Id → 查询参数 tenant → 环境变量 DEFAULT_TENANT"优先级解析租户上下文。请求级防护由 server/middleware/tenant-middleware.js 增强:tenantInject 注入 req.tenantContext(enterpriseId / role);tenantDataGuard 检测跨企业访问(目标 enterprise_id 与上下文不一致时)写入 audit_logs 审计记录并返回 403"跨租户访问被拒绝";quotaGuard 经 tenant-quota-service 校验配额,超限返回 429;SCSAIQueryFilter 还会把 注入 AML 查询,使数据检索天然限定在本企业范围内。
使用效果:每个客户的数据以独立 .db 文件存在,操作系统文件权限即可阻断跨租户读取;即便应用层发生越权尝试,也会被中间件拦截、审计并拒绝,且每次越权均留痕可追。备份、删除、迁移均可按租户粒度独立操作,互不干扰,满足 SaaS 多租户托管与数据主权合规要求。

图18-1 平台统一数据服务界面,体现多租户路由与隔离。
18.2 SQLite 引擎兼容与降级(v2 根治版)
功能背景:早期版本基于 sql.js(纯内存引擎)构建兼容层,存在"多模块加载同一 .db 成独立内存副本、互相 export 覆盖导致静默丢数""异常被空 catch 吞掉无法定位""路径写法混乱产生幽灵库"三大缺陷。最新版本将兼容层重构为 v2 根治版,核心目标是:对外保持 100% 兼容的旧 API,对内改用真正落盘的 SQLite 引擎,并具备引擎级自动降级能力,彻底消除静默丢数与幽灵库。
技术实现:server/sqlite-compat.js(v2,2026-07-15)在模块加载时优先 require('better-sqlite3') 作为主引擎(真实磁盘库,支持 WAL、真事务、多进程安全);若当前环境无编译条件,则 try/catch 优雅降级到 Node 22+ 内置的 node:sqlite(DatabaseSync),二者 prepare/run/all/get/exec/pragma/transaction/close 同步 API 高度一致,调用方零改动。canonicalPath() 将"已知库名"(KNOWN_DBS 集合,如 rule_engine.db、sciot_import.db、core_runtime.db 等)一律重定向到 server/data/,消除路径歧义;_instances(Map,按规范化绝对路径缓存)确保"同一物理文件 = 全局单例连接",根治多副本覆盖。开启 journal_mode = WAL 与 foreign_keys = ON 保证并发安全;采用 FAILFAST 策略,SQL 错误直接抛出并附 SQL 前 60 字符,不再静默吞掉;对损坏库通过 _backupCorrupt() 重命名为 .corrupt-<时间戳> 后重建,原数据留存可人工恢复。server/db-adapter.js 在此基础上再提供后端级降级:init() 在 DB_BACKEND=mysql 且 mysql-compat.init() 失败时,自动回退 _backend='sqlite' 走 sqlite-compat,业务代码无感。
使用效果:存储层从"易丢数的内存副本"升级为"单文件真磁盘库",数据持久性、并发安全性与可排查性大幅提升;运维无需关心 better-sqlite3 是否可编译,环境缺依赖时自动回退 Node 内置引擎;路径与单例治理消除了幽灵库与覆盖丢数,SQL 异常可第一时间定位。底层稳定性为上层多租户隔离、双后端适配与私有库同步提供了可靠基座。
#### 图18-2 SQLite 存储界面【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:SQLite 存储界面
- 截图保存为
../shots/sc3-1-storage.png后告知我,自动替换为正式图注
图18-2 存储初始化与表结构浏览界面(兼容层 v2 实况)。
18.3 双后端适配(SQLite / MySQL 统一适配)
功能背景:部分企业已建设 MySQL 集群,希望沿用既有数据库运维体系;另一些企业则要求零运维的本地文件库。同一套业务代码不应为两种后端重写 SQL。最新版本通过统一适配层,使 SQLite 与 MySQL 两种后端可经环境变量一键切换,并在方言层面完全透明。
技术实现:后端选择由 server/db-adapter.js 的 getBackend() 完成,读取 DB_BACKEND(sqlite / mysql),并兼容 n8n 的 DB_TYPE 环境变量。init() 在 MySQL 模式下 require('./mysql-compat') 并 await _adapter.init(),失败则回退 SQLite;createDatabase() 在未初始化时,SQLite 可同步工作,MySQL 未就绪则临时回退 SQLite 待 init() 完成后切换。方言工具 nowExpr()、autoIncrementPK()、textPK()、getConvertSQL() 屏蔽两类后端差异(如 SQLite 的 datetime('now','localtime') 与 MySQL 的 NOW())。MySQL 适配由 server/mysql-compat.js 实现:在 Worker Thread 中运行 mysql2/promise 连接池(connectionLimit 10、utf8mb4、enableKeepAlive),通过 SharedArrayBuffer + Atomics.wait/notify 把异步的 MySQL 访问"同步化"以贴合兼容层同步 API;convertSQL(sql) 完成一套完整的方言转换(INTEGER PRIMARY KEY AUTOINCREMENT→INT AUTO_INCREMENT PRIMARY KEY、TEXT PRIMARY KEY→VARCHAR(255) PRIMARY KEY、PRAGMA→注释、REAL→DOUBLE、sqlite_master→information_schema.tables、INSERT OR IGNORE→INSERT IGNORE 等);transaction() 映射为 START TRANSACTION / COMMIT / ROLLBACK。server/database1.js 的 DatabaseManager 以懒加载单例(_ensureDb())获取连接,并检测后端变化(SQLite→MySQL)自动 close() 重建;init() 依次执行 _createTables()、_createIndexes()、_runMigrations()。统一的 server/shared/db.js 进一步收敛全站混乱的 DB 访问路径(db-adapter→database→global._pvDb 三级回退),对外只暴露 init / exec / query / findOne / execute / isConnected,全部防御式处理,不再抛"未初始化"错误。
使用效果:部署方可按既有 IT 资产在 SQLite(零运维、离线可用)与 MySQL(复用集群、集中运维)之间自由切换,业务代码、建表 DDL、查询 SQL 一概无需改写;方言自动转换让同一份 SQL 在两种后端行为一致;统一访问层消除了多套 DB 引用路径带来的不确定性,提升了全站可维护性与稳定性。
#### 图18-3 SQLite 存储平台总览【界面图·待补真实截图】
- 截图来源:网页端 BossAgents
- 应展示:SQLite 存储平台总览
- 截图保存为
../shots/sc3-2-platform.png后告知我,自动替换为正式图注
图18-3 平台数据服务/存储内容浏览界面(双后端适配支撑的统一数据层)。
18.4 私有库存储与企业管理对象镜像(PrivateStorage)
功能背景:企业的核心工业对象(零件、项目、工艺等)往往同时存在于 SCSAI(MSSQL Server)等既有 PDM/PLM 系统中。若每次浏览、搜索都直接打 SCSAI,既慢又强耦合;而本地若无私有镜像,又难以做快速检索与离线查阅。最新版本新增"企业私有库存储层",以本地 SQLite 作为 SCSAI 对象的私有镜像,实现"读本地快、写回源系统、再同步本地"的私有库范式,并配套前端管理界面。
技术实现:server/utils/private-store.js 以 data/enterprise_store.db 为私有库文件,建表 enterprise_objects(字段 id、object_type、keyed_name、aml_content、properties_json、source、source_id、created_at、updated_at、created_by、version),并对 object_type、keyed_name、source、created_at 建索引。其读写策略为:查询 / 浏览 / 搜索走本地 SQLite(快速、不依赖 SCSAI),而增 / 改 / 删仍走 SCSAI API,操作完成后再增量同步回本库。save(objectType, id, keyedName, amlContent, propertiesJson, options) 先 SELECT 查重以决定 created_at,再用 INSERT OR REPLACE 落库并 version + 1,保证标准→私有的增量同步与版本演进;list / listAll 支持分页,search 用 LIKE 关键词检索,exactMatch 借助 json_extract(properties_json, …) 精确匹配属性值,fuzzyMatch 基于 Jaccard 相似度对对象名做模糊匹配(默认阈值 0.85),getTypes / getStats 提供类型分布与总量统计。配套前端 src/views/PrivateLibrary.vue 提供完整管理界面:左侧"对象类型树"(含总量与各类型计数),右侧"对象列表"(表格展示类型 / 名称 / ID / 来源 / 版本 / 更新时间,分页浏览),顶部搜索栏支持关键词检索;点击行可弹出"详情弹窗",以选项卡分别展示属性键值表与原始 AML(aml_content),并提供"AML"查看与"删除"操作;来源以徽标区分 created / copied_from_standard / synced_from_SCSAI,清晰呈现数据主权归属。
使用效果:企业用户获得一个"既私有、又快、又可追溯"的工业对象管理底座——日常浏览与搜索在本地私有库毫秒级返回,不挤占 SCSAI;关键环节的写操作仍经权威源系统落账,再增量同步回本地镜像,兼顾一致性与性能;前端界面让非技术人员也能直观浏览、检索、核对对象属性与 AML 原文,并随时查看数据来源与版本演进,显著提升私有工业数据的可管理性与可审计性。

图18-4 私有库数据落库与浏览界面(企业私有对象镜像)。
附录 A:基于最新代码补充的新增功能(2026年7月)
A.1 SQLite 兼容层原生绑定运行时校验与自动降级
server/sqlite-compat.js 进一步增强兼容性鲁棒性:以往"require 成功即认为可用"存在隐患——若 npm install 跳过了原生编译,better-sqlite3 会在运行时静默失败。本次在加载时增加原生绑定运行时校验:require('better-sqlite3') 后,立即用内存库执行 prepare('SELECT 1').get() 真实可用性验证;验证通过才采用该引擎,否则置空并降级到 Node 22+ 内置 node:sqlite 的 DatabaseSync,二者皆不可用时抛出明确错误。结合既有的单例缓存、WAL 并发安全与损坏库"备份→重建"自愈机制,该兼容层作为全仓库数据层基础,保障了在不同部署环境(含原生模块缺失场景)下的稳定启动与私有数据可用。
说明:本节描述的原生绑定校验与降级逻辑,当前为工作树中尚未提交的改动(相对最近一次软著快照),属存储模块已具备的兼容性增强。
著作权人信息
以下著作权人信息与中国版权保护中心登记申请表一致,供审查核对。
- 著作权人: 北京左帮右臂人工智能技术有限公司
- 著作权人类型: 法人(有限责任公司·自然人独资)
- 证件类型: 营业执照
- 统一社会信用代码: 91110114MAKJ1UC63J
- 注册地址: 北京市昌平区东小口镇天通中苑二区21号楼1层103-2819(集群注册)
- 联系人: 方云超
- 联系电话: 18601921816
- 电子邮箱: [email protected]
- 邮政编码: 100010
BossAgents