迁移全局唯一 ID
在内置全局 ID 功能标志之前,迁移工具提供了 WithGlobalUniqueID 选项,允许用户将模式迁移为使用全局唯一 ID。该选项现已弃用,用户应改用全局 ID 功能标志。现有用户可按以下步骤将模式迁移为使用全局唯一 ID。
先前方案使用名为 ent_types 的表来存储 Ent 模式与其关联 ID 范围的映射信息。新方案使用静态配置文件存储此映射。要迁移到新的全局 ID 功能,可使用 entfix 命令将现有的 ent_types 表迁移至新配置文件。
请注意,'ent_types' 表在应用部署的不同环境中可能存在差异。如果使用自动迁移而非版本化迁移,这一点尤为明显。请检查所有部署环境中的 'ent_types' 表是否一致。若存在差异,则无法转换到新的全局 ID 功能。
第一步通过运行以下命令安装 entfix 工具:
go install entgo.io/ent/cmd/entfix@latest
接下来可运行 entfix globalid 命令将模式迁移为使用全局 ID 功能。该命令需要访问数据库以读取 ent_types 表。可连接已部署的数据库,或连接只读副本,若使用版本化迁移,则可连接已应用所有迁移的临时数据库。
entfix globalid --dialect mysql --dsn "root:pass@tcp(localhost:3306)/app" --path ./ent
重要信息
'entfix globalid' 将把数据库中 'ent_types' 表分配的节点 ID 范围
迁移至 ent 模式本身的静态配置中。
请注意,'ent_types' 表在应用部署的不同环境中可能存在差异。
如果使用自动迁移而非版本化迁移,这一点尤为明显。
请检查所有部署环境中的 'ent_types' 表是否一致!
仅输入 'yes' 表示确认。
请输入:yes
成功!请运行代码生成以完成该过程。
最后再次运行代码生成完成迁移。应在生成代码中看到新文件 internal/globalid.go,其中仅包含以 const IncrementStarts 开头的单行代码,表明流程已成功完成。最后一步是确保从迁移设置中移除 migrate.WithGlobalUniqueID(true) 选项。
可选:保留 ent_types 表
若希望保留数据库中的 ent_types 表,在确认无需回滚计算前不删除该表,可使用 Atlas 复合模式实现:
- schema.my.sql
- atlas-hcl
schema "ent" {}
table "ent_types" {
schema = schema.ent
collate = "utf8mb4_bin"
column "id" {
null = false
type = bigint
unsigned = true
auto_increment = true
}
column "type" {
null = false
type = varchar(255)
}
primary_key {
columns = [column.id]
}
index "type" {
unique = true
columns = [column.type]
}
}
data "composite_schema" "ent" {
schema "ent" {
url = "ent://./ent/schema?globalid=static"
}
# 此配置用于暂时保留 ent_types 表
schema "ent" {
url = "file://./schema.my.hcl"
}
}
env {
name = atlas.env
src = data.composite_schema.ent.url
dev = "docker://mysql/8/ent"
migration {
dir = "file://./ent/migrate/migrations"
}
}
全局唯一 ID(已弃用的迁移选项)
默认情况下,SQL 主键从每个表的 1 开始计数;这意味着不同类型的多个实体可以共享相同的 ID。这与 AWS Neptune 不同,后者的节点 ID 为 UUID。
这在处理 GraphQL 时效果不佳,因为 GraphQL 要求对象 ID 必须唯一。
要为项目启用全局唯一 ID 支持,请将 WithGlobalUniqueID 选项传递给迁移。
版本化迁移用户在使用 WithGlobalUniqueID 时,若使用 MySQL 5.*,请遵循文档说明。
package main
import (
"context"
"log"
"<project>/ent"
"<project>/ent/migrate"
)
func main() {
client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test")
if err != nil {
log.Fatalf("failed connecting to mysql: %v", err)
}
defer client.Close()
ctx := context.Background()
// 运行迁移
if err := client.Schema.Create(ctx, migrate.WithGlobalUniqueID(true)); err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}
}
工作原理:ent 迁移为每个实体(表)的 ID 分配 1<<32 的范围,并将此信息存储在名为 ent_types 的表中。例如,类型 A 的 ID 范围为 [1,4294967296),类型 B 的 ID 范围为 [4294967296,8589934592),依此类推。
请注意,启用此选项后,最大可能表数为 65535。