SpacetimeDB 数据库模块完全指南:Module 与 Database 的核心区别及 spacetime CLI 全生命周期管理
2026/9/13 11:32:16 网站建设 项目流程

SpacetimeDB 数据库模块完全指南:Module 与 Database 的核心区别及 spacetime CLI 全生命周期管理

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

SpacetimeDB 的模块(Module)与数据库(Database)是一对极易混淆但至关重要的概念:模块是你编写的代码(表结构与服务端逻辑),而数据库是该模块真正运行起来、承载实际数据与客户端连接的实例。本文以官方核心概念文档为主线,结合本仓库的 CLI 源码实现,系统讲解两者区别、模块构成、支持的语言生态、数据库命名规则,以及使用spacetimeCLI 完成创建、更新、删除、查询、日志与列表管理的完整实操。

什么是 Module(模块)

Module(模块)是「代码」这一层抽象:它是函数与 schema(表结构)定义的集合,可以用 TypeScript、C#、Rust 或 C++ 编写。模块定义了数据库的结构,以及负责处理和响应客户端请求的服务端逻辑。通俗地说,模块就是你的业务程序本身。

Module 与 Database 的区别

理解二者区别是整个 SpacetimeDB 使用模型的基石:

  • Module 是你写的代码。它定义了 schema(表)与业务逻辑(reducers、procedures、views)。模块需要被编译并发布(deploy)到 SpacetimeDB 上。Rust、C#、C++ 模块会编译为 WebAssembly(Wasm),而 TypeScript 模块运行在 V8 引擎上。
  • Database 是模块的"运行实例"。它拥有模块的 schema 与逻辑,外加真实存储的数据

两者关系可以类比为「类与对象」或「程序与进程」:同一份模块代码,可以发布到多个数据库——例如分别用于测试、预发(staging)、生产环境,每个数据库各自拥有独立的数据。

关于重发布(republish)的重要事实:当你更新模块代码并重新发布时,SpacetimeDB 会更新数据库的 schema 与逻辑,已有数据会保留。不过对于复杂 schema 变更,你需要谨慎处理迁移(migration),因为并非所有改动都能自动完成——详见后文「自动迁移」相关章节。

从源码结构看,数据库的删除与发布请求都直接作用于数据库的 identity,例如 publish.rs 中以PUT /v1/database/{domain}创建或更新数据库、以POST /v1/database匿名创建,这印证了「数据库是可寻址的运行实体」这一设计。

Module 里有什么

一个模块包含以下组成部分:

  • Tables(表)—— 定义数据结构与存储。
  • Reducers(归约器)—— 以事务方式修改数据的服务端函数。
  • Procedures(过程)—— 可以执行外部操作(如 HTTP 请求)并返回结果的函数。
  • Views(视图)—— 基于数据之上的只读计算查询。

模块的服务端逻辑正是由这三类函数承载:reducers(事务性状态变更)、procedures(具备外部能力的函数)、views(只读查询)。

支持的模块语言

SpacetimeDB 模块可以用多种语言编写,均获得完整支持:

语言适用场景运行载体快速入门
TypeScript熟悉 JavaScript/Node.js 的开发者V8 引擎TypeScript 快速入门
C#使用 Unity 或 .NET 的开发者WebAssembly(默认),亦支持 NativeAOT-LLVM 实验编译C# 快速入门
Rust追求高性能的开发者WebAssemblyRust 快速入门
C++Unreal Engine 或 C++ 生态开发者WebAssemblyC++ 快速入门

需要说明的是,C++ 模块的完整支持存在版本前提(文档中的CppModuleVersionNotice组件会提示具体版本条件)。C# 模块还可通过spacetime publish --native-aot启用 NativeAOT-LLVM 编译(实验特性,支持 Windows,以及 .NET 10 环境下的 Linux),相关参数定义可见 publish.rs。

数据库命名规则

当你发布一个模块时,需要为数据库起一个名字。数据库名必须匹配正则表达式/^[a-z0-9]+(-[a-z0-9]+)*$/,即:只能包含小写 ASCII 字母和数字,并用连字符(-)分隔

合法示例:

  • my-game-server
  • chat-app-production
  • test123

该正则的具体实现位于 name.rs,其parse_database_name函数逐字符校验,可总结出以下更精细的约束规则:

  • 名字不能为空
  • 首字符必须是a-z0-9不能以-开头
  • 不能以-结尾
  • 不能出现连续两个-
  • 除小写字母与数字外的任何字符(包括大写字母、下划线、空格)都会报错;
  • 名字不能是 identity 字符串(即不能把数据库身份标识当作名字使用,DatabaseNameError::Identity会拒绝此类输入)。

每个数据库在创建时还会获得一个唯一的 identity(十六进制字符串)。客户端既可以用名字连接,也可以用 identity 连接。在 CLI 内部,validate_name_or_identity(见 publish.rs)会先判断参数是否为 identity,若不是则走上述数据库名校验;如果误将 identity 当作普通名字,parse_database_name会给出明确的「数据库名不能是 identity」错误。

使用 spacetime CLI 管理数据库

模块与数据库的日常管理全部通过spacetimeCLI 工具完成。下面按生命周期顺序逐一讲解,并补充源码中的参数细节。

创建与更新数据库(spacetime publish)

创建或更新数据库的唯一方式是发布你的模块

spacetime publish <DATABASE_NAME>

该命令的完整行为可参见spacetime publish详解文档 与 CLI 参考。从 publish.rs 的cli()定义可看到,spacetime publish还支持以下常用参数:

参数作用
<DATABASE_NAME>数据库名或 identity;若传parent/child形式则同时指定父数据库
-p, --module-path <PATH>模块项目路径(默认优先取spacetimedb/子目录,再取当前目录)
-b, --bin-path <PATH>跳过构建,直接发布编译好的 Wasm 二进制
-j, --js-path <PATH>不稳定:跳过构建,直接发布 JS 文件(TypeScript 模块)
--build-options <OPTS>传递给构建命令的选项(如--build-options='--lint-dir='
--break-clients允许对已存在数据库做破坏性变更(跳过「将破坏现有客户端」确认,等价于--yes=break-clients;但不会强制发布会导致数据删除的变更)
--clear-database清空数据库数据后发布(always/on-conflict/never,需配合名字使用)
--parent <DOMAIN_OR_IDENTITY>为数据库指定父数据库(仅创建时生效),新数据库会继承父数据库的团队权限
--organization <NAME_OR_IDENTITY>将数据库创建到某个组织下(仅创建时生效),组织的成员权限会应用于新数据库
--yes[=<类别>]跳过确认提示,取值可为allremotemigratebreak-clientsskip-logindelete-data(可逗号分隔或用多个--yes=),需用=连接
--no-config忽略spacetime.json配置
--env <ENV>配置文件分层环境名(如 dev、staging)
--num-replicas <N>不稳定:数据库副本数
--native-aotC# 模块使用 NativeAOT-LLVM 编译(实验特性)

重发布时的迁移行为:当你对已存在的数据库重新发布时,SpacetimeDB 会先调用pre_publish接口做「破坏性变更检查」(CLI 输出Checking for breaking changes...)。根据 publish.rs 中apply_pre_publish_if_needed的实现,检查结果分为两种情况:

  • AutoMigrate(自动迁移):打印迁移计划;若变更会破坏现有客户端(break_clients为 true),会要求确认「The above changes will BREAK existing clients」,可通过--break-clients--yes=break-clients跳过。
  • ManualMigrate(手动迁移):打印原因并中止发布,除非指定了--clear-database=on-conflict(此时会清库重发,需要--yes=delete-data确认)。
  • 若目标数据库不存在(HTTP 404),则视为全新发布,跳过全部检查。

此外,若检测到主版本升级(如 1.x → 2.0),CLI 会要求手动输入upgrade确认,无法通过常规--yes静默跳过,因为此操作不可回退。相关细节可参考 1.x 到 2.0 升级说明。

迁移进阶主题

  • 自动迁移(Automatic Migrations) —— 哪些 schema 变更是安全的、破坏性的或禁止的。
  • 增量迁移(Incremental Migrations) —— 处理复杂 schema 变更的高级模式。

删除数据库(spacetime delete)

永久删除一个数据库及其全部数据:

spacetime delete <DATABASE_NAME>

CLI 会提示你确认删除操作;在脚本中可用--yes跳过确认(对应 delete.rs 中的force标志,提示语为 "Are you sure you want to delete database ...? This action cannot be undone.")。

警告:删除数据库是永久性操作,无法撤销,所有数据都会丢失。

从 delete.rs 源码看,删除还包含一个安全细节:如果目标数据库存在子数据库(通过--parent建立的数据库树),服务端会返回428 PRECONDITION_REQUIRED,CLI 会打印整棵数据库树(类似tree命令的树形结构,展示各节点的 identity 与关联名字),并要求二次确认「Deleting the database ... will also delete its children!」。确认后会携带confirmation_token再次发起删除请求。可用--no-config忽略spacetime.json中的数据库目标。更多选项见 CLI 参考。

用 SQL 查询数据库(spacetime sql)

可以直接对数据库执行 SQL 查询:

spacetime sql <DATABASE_NAME> "SELECT * FROM user"
所有者权限(Owner Privileges)

重要:以数据库所有者身份执行 SQL 查询时,会绕过表可见性限制——也就是说,你可以查询普通客户端无法访问的私有表。

若想以无特权客户端视角测试查询结果,使用--anonymous标志:

spacetime sql --anonymous <DATABASE_NAME> "SELECT * FROM user"

该查询会以匿名客户端身份执行,严格遵守表可见性规则。

从 sql.rs 源码可补充以下实用细节:

  • --interactive:进入交互式 SQL 提示符模式(spacetime sql [database] --interactive),底层调用 REPL 循环。
  • --format <FORMAT>:输出格式,默认为text(psql 风格表格,用+/-分隔),也可指定json输出原始 JSON 结果。
  • 执行 DML 语句时,结果表格下方会附带统计信息,例如(0 rows) [inserted: 1, deleted: 1, updated: 1, server: 1.00ms],展示插入/删除/更新的行数与服务端耗时(该行为由StmtResultDisplay实现产生,相关测试见 sql.rs 中的test_output等用例)。
  • 未显式指定数据库时,若项目根目录存在spacetime.json,会自动使用其中的数据库目标。

更多 SQL 选项见 CLI 参考,SQL 语法可参考 SQL 参考文档。

查看日志(spacetime logs)

查看数据库日志:

spacetime logs <DATABASE_NAME>
实时跟随日志

类似tail -f的流式日志输出:

spacetime logs --follow <DATABASE_NAME>

该命令会保持连接打开并持续显示新产生的日志条目,按Ctrl+C停止。从 logs.rs 源码看,--follow且未指定行数时默认先输出最近 10 行再开始跟随。

限制日志输出量

只查看最后 N 行:

spacetime logs --num-lines 100 <DATABASE_NAME>

--num-lines(或-n)用于指定从日志开头起打印的行数;若完全不指定则返回全部日志。

日志等级过滤

logs.rs 还提供了两个实用过滤参数:

  • -l, --level <LEVEL>:按严重级别过滤,级别从低到高为tracedebuginfowarnerrorpanic,只显示达到或超过该级别的日志;
  • --level-exact:配合--level使用,只显示恰好等于该级别的日志。

文本模式下终端还会按级别着色(如 ERROR 红色、WARN 黄色、INFO 蓝色等),支持--format json输出结构化日志。更多日志选项见 CLI 参考,模块内如何打日志可参考 日志指南。

列出你的数据库(spacetime list)

查看当前身份关联的全部数据库:

spacetime list

该命令会显示数据库名、identity 与所在主机服务器。从 list.rs 源码看,它以当前登录用户的 identity 查询/v1/identity/{identity}/databases接口,再对每个数据库做反向 DNS 解析得到名字,最终以 psql 风格表格输出,表头为Database Name(s)Identity(同一 identity 可能关联多个名字,会以逗号分隔列出)。

通过网站管理数据库

除了 CLI,还可以通过 SpacetimeDB 的 Web 界面(spacetimedb.com)管理数据库,支持:

  • 查看指标(View metrics)—— 监控数据库性能、连接数与资源使用;
  • 浏览表(Browse tables)—— 查看表 schema 与数据;
  • 查看日志(View logs)—— 访问带过滤与搜索的历史日志;
  • 管理访问权限(Manage access)—— 控制数据库权限与团队访问;
  • 监控查询(Monitor queries)—— 查看订阅查询与 reducer 调用。

网站为大部分 CLI 操作提供了图形化界面,便于可视化地查看和管理数据库。

Projects 与 Teams

SpacetimeDB 支持将数据库组织为项目(Projects)并管理团队访问(team access),从而:

  • 将相关的数据库分组管理;
  • 与团队成员共享访问权限;
  • 在项目层面统一管理权限。

此外,如前文所述,数据库之间还可以通过--parent建立父子层级(子数据库继承父数据库的团队权限),这为多环境、多租户的权限组织提供了更细的粒度。

学习路径

快速上手

如果你是 SpacetimeDB 新手,推荐按以下顺序学习:

  1. 创建你的第一个数据库模块—— 用spacetime initspacetime dev搭建模块项目;
  2. 构建并发布—— 学习如何编译并部署模块;
  3. 定义表—— 用表、列与索引组织数据;
  4. 编写 Reducers—— 创建以事务方式修改数据库的函数;
  5. 连接客户端—— 构建连接数据库的客户端应用。

核心概念

掌握基础后,继续深入这些核心主题:

  • 错误处理(Error Handling)—— 在 reducers 中优雅处理错误;
  • 生命周期 Reducers(Lifecycle Reducers)—— 响应初始化、客户端连接等系统事件;
  • 自动迁移(Automatic Migrations)—— 理解 schema 变更如何生效;
  • 日志(Logging)—— 用日志调试和监控模块。

高级特性

  • Procedures—— 发起 HTTP 请求、与外部服务交互;
  • Views—— 创建可计算、可订阅的查询;
  • 调度表(Schedule Tables)—— 在指定时间调度 reducers 运行;
  • 增量迁移(Incremental Migrations)—— 处理复杂 schema 变更;
  • SQL 查询—— 用 SQL 查询数据库。

部署上线

  • 部署到 MainCloud—— 将数据库托管到 SpacetimeDB 的托管服务;
  • 自托管(Self-Hosting)—— 运行自己的 SpacetimeDB 实例(仓库内对应的独立服务器入口与配置见 standalone 与 config.toml)。

下一步

  • 学习 Tables 定义数据库 schema;
  • 创建 Reducers 修改数据库状态;
  • 理解 Subscriptions(订阅) 实现实时数据同步;
  • 查阅 CLI 参考 了解全部可用命令。

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询