SurrealDB 可用于分布式场景,但需手动配置集群且不支持开箱即用的自动分片;Go 必须使用 surrealdb-go 驱动,通过 WebSocket 或 HTTP 连接,显式认证,定义多模型 schema,手动管理事务,Live Query 受权限规则服务端过滤,集群需正确注册节点并健康检查。

能用,但得清楚它不是传统意义上的“分布式数据库”——SurrealDB 的分布式能力依赖集群模式 + 正确配置,不是开箱即用的 CockroachDB 那种自动分片。
Go 连接 SurrealDB:用官方 surrealdb-go 驱动而非 generic SQL driver
SurrealDB 不兼容 database/sql 标准驱动(比如 pgx 或 mysql),必须用专用 Go SDK:surrealdb-go。它封装了 WebSocket 和 HTTP 协议,支持连接单节点或集群入口。
- 安装:
go get github.com/surrealdb/surrealdb.go - 连接时指定协议:
ws://localhost:8000/rpc(推荐 WebSocket,支持 Live Query)或http://localhost:8000/sql(仅同步查询) - 认证必须显式传入 token 或凭据;即使本地开发,也需先调用
signin方法获取 session token,不能跳过 - 注意:v1.0+ 版本要求服务端启用
--auth参数,否则signin会返回Unauthorized
定义多模型结构:用 DEFINE TABLE + SCHEMA FULL + COMPUTED 字段
SurrealDB 的“多模型”不靠建多个库或切换引擎,而靠同一张表内混合使用关系约束、文档嵌套和图语义。Go 侧只需按 SurrealQL 定义好 schema,驱动会原样提交。
-
DEFINE TABLE user SCHEMA FULL允许动态字段,同时支持DEFINE FIELD email ON user TYPE string ASSERT $value =~ /^[^@]+@[^@]+\.[^@]+$/做校验 - 嵌套文档直接存 JSON:
DEFINE FIELD profile ON user TYPE object,Go 中用map[string]interface{}或结构体序列化即可 - 图关系用
->语法,无需外键约束:插入时写RELATE user:alice->follows->user:bob,查询时SELECT ->follows->name FROM user:alice - 避免在 Go 层做 JOIN 拼接;把关联逻辑写进 SurrealQL,比如
SELECT *, ->orders.* AS orders FROM user WHERE id = $id
并发与事务:用 BEGIN/COMMIT 显式控制,别依赖 auto-commit
SurrealDB 默认不开启自动事务,每个查询独立执行。需要强一致性时,必须手动包裹 BEGIN / COMMIT 或用 QUERY 批量提交。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
立即学习“go语言免费学习笔记(深入)”;
- Go 中调用
db.Query("BEGIN; ... ; COMMIT;", nil)是最稳妥方式;db.Create()等快捷方法不参与事务 - Live Query 订阅(
LIVE SELECT)和事务互斥:事务中修改数据不会触发 live query 推送,直到COMMIT后才广播 - 集群模式下,事务跨节点时受
quorum配置影响;若节点数为 3,缺一个节点就无法提交,这点比 PostgreSQL 更敏感 - 错误码
NS-ERR-001表示事务冲突,不是网络超时,需重试逻辑而非简单 log
部署集群时:Go 客户端只连 coordinator,不直连单个 node
SurrealDB 集群没有 ZooKeeper 或 etcd 协调层,而是靠内置的 Raft 实现 leader 选举。Go 应用只需连接任意一个节点的 RPC 地址,它会自动转发请求到当前 leader。
- 启动集群命令示例:
surreal start --bind 0.0.0.0:8000 --cluster http://node1:8001,http://node2:8001,http://node3:8001 --user root --pass root - Go 连接地址仍用
ws://node1:8000/rpc,不要轮询或负载均衡多个地址——驱动内部不做重试路由,失败就是失败 - 集群健康检查不能只 ping 端口;要发
INFO查询看status字段是否为ok,且nodes列表包含全部预期节点 - 横向扩容时,新节点加入后需手动执行
DEFINE NODE ...注册,否则不参与数据分片
真正容易被忽略的是权限策略与 Live Query 的耦合:一旦在表上定义了 PERMISSIONS FOR select WHERE $auth.id == $value.user_id,Live Query 推送的数据也会被该规则过滤——不是客户端收到全量再过滤,是服务端压根不推送。这点和普通 SELECT 一致,但开发者常误以为 live 是“原始变更流”。

















