从托管托管数据库迁移到本地数据库服务器:sqlc 的 servers 配置迁移指南
2026/9/21 7:33:29 网站建设 项目流程

从托管托管数据库迁移到本地数据库服务器:sqlc 的 servers 配置迁移指南

【免费下载链接】sqlcGenerate type-safe code from SQL项目地址: https://gitcode.com/gh_mirrors/sq/sqlc

从 sqlc 1.27.0 开始,managed databases(托管数据库)功能要求配置文件提供数据库服务器 URI;从 sqlc 1.31.1 起,配置中新增了顶层servers映射,用于声明可供查询分析使用的本地数据库服务器连接。本指南基于官方迁移文档,完整讲解如何将原先依赖托管数据库的 sqlc 项目迁移到本地运行的 MySQL/PostgreSQL 服务器上,涵盖本地数据库启动、sqlc 升级、servers配置写入以及重新生成代码的全过程,并结合仓库源码揭示sqlc_managed_前缀数据库的自动创建机制。

背景:为什么需要迁移

sqlc 的 managed databases 特性(自 v1.22.0 引入,详见 托管数据库指南)可以让 sqlc 自动创建只读数据库,为查询分析(query analysis)、lint 检查(sqlc vet)和验证(sqlc verify)提供真实的数据库环境。相比纯静态解析,连接真实数据库能让 sqlc 对复杂查询生成更准确的类型安全代码。

从 v1.27.0 开始,managed databases 不再使用云端隐式托管,而是要求在你的配置文件中显式提供一个数据库服务器的 URI(连接字符串)。这意味着项目必须能访问到一个真实运行的数据库服务器。为了让迁移过程更平滑,v1.31.1 又引入了顶层servers配置段,允许在配置中声明一个或多个数据库服务器,供 managed database 逻辑按引擎匹配使用。

因此,本指南的目标是把项目的查询分析底座从"托管"迁移到"本地运行的真实数据库服务器",整体分三步走:

  1. 在本地启动数据库服务器(推荐 Docker Compose,同时支持 MySQL 与 PostgreSQL);
  2. 升级 sqlc 到 v1.31.1 或更高版本,以使用servers配置;
  3. 在配置文件中添加servers映射,并重新执行sqlc generate

第一步:在本地运行一个数据库服务器

本地运行数据库服务器的方案很多,官方迁移指南推荐使用 [Docker Compose](可同时支持 MySQL 和 PostgreSQL);如果你在 macOS 上使用 PostgreSQL,[Postgres.app] 也是不错的选择。

说明:本指南中的 Docker Compose 配置与端口均以官方迁移文档为准,请根据你本机实际占用情况调整端口映射。

使用 Docker Compose 启动 MySQL

创建docker-compose.yml,内容如下:

version: "3.8" services: mysql: image: "mysql/mysql-server:8.0" ports: - "3306:3306" restart: always environment: MYSQL_DATABASE: dinotest MYSQL_ROOT_PASSWORD: mysecretpassword MYSQL_ROOT_HOST: '%'

要点说明:

  • MYSQL_DATABASE: dinotest:容器启动时自动创建的初始数据库名,后续 sqlc 会在该服务器上以sqlc_managed_前缀另建分析用数据库;
  • MYSQL_ROOT_PASSWORD:root 用户的密码,对应后续servers.uri连接串中的密码部分;
  • MYSQL_ROOT_HOST: '%':允许任意主机通过 root 连接,避免容器网络下连接被拒;
  • 3306:3306:将容器 3306 端口映射到宿主机,servers.uri中的localhost:3306即访问此端口。

使用 Docker Compose 启动 PostgreSQL

若使用 PostgreSQL,创建如下docker-compose.yml

version: "3.8" services: postgresql: image: "postgres:16" ports: - "5432:5432" restart: always environment: POSTGRES_DB: postgres POSTGRES_PASSWORD: mysecretpassword POSTGRES_USER: postgres

要点说明:

  • POSTGRES_USER/POSTGRES_PASSWORD:数据库超级用户及密码,对应连接串中的用户名和密码;
  • POSTGRES_DB: postgres:初始默认数据库;
  • 5432:5432:映射到宿主机的 PostgreSQL 默认端口。

启动服务:

docker compose up -d

启动后,可通过docker compose ps确认容器状态,并验证端口连通性(例如mysql -h127.0.0.1 -P3306 -uroot -ppsql -h localhost -p 5432 -U postgres)。

第二步:升级 sqlc

servers配置项需要较新的 sqlc 版本。官方迁移指南明确要求:

必须运行sqlc v1.31.1 或更高版本,才能使用servers配置。

从仓库的 变更日志 可以看到相关演进脉络:

  • v1.27.0 引入了 "Managed databases with any accessible server",managed databases 开始面向任意可访问的数据库服务器;
  • 同版本还收录了 "Add migration guide for hosted managed databases" 的文档变更,正是本指南所对应的迁移文档。

升级方式取决于你的安装渠道(如go install、Homebrew、预编译二进制等),请以官方安装方式为准。升级完成后可用sqlc version确认版本号。

第三步:向配置中添加 servers

servers是配置文件(sqlc.yaml/sqlc.yml/sqlc.json,详见 配置参考)中的顶层映射。官方迁移指南给出的 diff 如下:

version: '2' cloud: project: '<PROJECT_ID>' + servers: + - name: mysql + uri: mysql://localhost:3306 + - name: postgres + uri: postgres://localhost:5432/postgres?sslmode=disable

从源码结构看,servers对应 internal/config/config.go 中的Config.Servers []Server字段,每个Server包含三个可选字段:

字段类型说明
namestring服务器名称,便于识别(json:"name,omitempty",可选)
enginestring引擎标识,取值如mysqlpostgresql(可选)
uristring数据库服务器连接 URI(必填)

其中引擎常量定义于同一文件的 internal/config/config.go:mysqlpostgresqlsqliteclickhousegooglesqlmssqlduckdb。不过需要注意,managed database 的自动建库逻辑目前只支持 MySQL 与 PostgreSQL(详见下文原理分析)。

同时使用 MySQL 与 PostgreSQL

如果你的项目同时包含 MySQL 和 PostgreSQL 的查询集,可以在servers中并列声明两台服务器,由 managed 客户端按引擎自动匹配(这一点可在 internal/dbmanager/client.go 的源码中看到:遍历servers列表,按server.Engine == engine选择对应的URI)。

结合managed: true的完整配置示例如下(对齐 托管数据库指南 的格式):

version: '2' servers: - name: mysql engine: mysql uri: "mysql://root:mysecretpassword@localhost:3306/dinotest" - name: postgres engine: postgresql uri: "postgres://postgres:mysecretpassword@localhost:5432/postgres?sslmode=disable" sql: - schema: schema.sql queries: query.sql engine: postgresql database: managed: true gen: go: out: "db"

使用环境变量(推荐)

连接串中可能包含密码等敏感信息,官方文档推荐使用${}语法引用环境变量,避免将凭据硬编码进配置文件:

version: '2' servers: - engine: postgresql uri: ${DATABASE_URI} sql: - schema: schema.sql queries: query.sql engine: postgresql database: managed: true

从源码实现看,URI 中的${...}占位符会在运行时由 internal/shfmt 的Replacer展开:dbmanager客户端在创建连接前调用m.replacer.Replace(base)完成替换(见 internal/dbmanager/client.go),因此密码等敏感信息可以安全地放在环境变量中。

与 cloud 配置的关系

迁移前配置文件中的cloud.project用于关联 sqlc Cloud 项目;迁移到本地服务器后,serverscloud相互独立、可以并存。如果你不再使用云端服务,保留或移除cloud段均可,servers段负责提供本地连接。若项目未配置servers却使用了managed: true,运行时将报错no PostgreSQL database server found(错误文案见 internal/dbmanager/client.go),这正是迁移后最常见的问题之一。

第四步:重新生成代码

完成配置后,在项目根目录执行:

sqlc generate

官方迁移指南指出:一个带有sqlc_managed_前缀的数据库会被自动创建,并用于查询分析。

sqlc_managed_数据库的底层原理

这一行为的实现位于 internal/dbmanager/client.go 的ManagedClient.CreateDatabase,其工作流程可以概括为:

  1. 计算数据库名:以查询集 schema 的 SQL 内容(Migrations)为输入,用 FNV-64 哈希生成一个固定 ID,再拼接前缀得到数据库名sqlc_managed_<hash>(若调用方未显式指定Prefix,默认前缀即sqlc_managed,见 internal/dbmanager/client.go)。由于名称由 schema 内容哈希决定,同一 schema 的后续运行会复用同名数据库;
  2. 按引擎匹配服务器:遍历配置中的servers,找到与查询集引擎一致的服务器 URI;当前仅放行mysqlpostgresql两种引擎,其他引擎直接返回unsupported engine错误(internal/dbmanager/client.go);
  3. 幂等建库:先查询pg_database判断数据库是否已存在;不存在则执行CREATE DATABASE,并通过singleflight保证并发运行只建一次;
  4. 应用 schema:连接到新库,逐条执行查询集的 DDL(migrations);任一条失败则DROP DATABASE ... WITH (FORCE)回滚清理(internal/dbmanager/client.go)。

也就是说,sqlc generate会自动完成"建库 → 灌入 schema → 用真实数据库做查询分析 → 按查询缓存分析结果"的完整链路,这也是 managed databases 相比纯静态解析能显著提升复杂查询代码质量的原因。

顺带一提:sqlc createdb

仓库还提供了sqlc createdb命令("Create an ephemeral database",见 CLI 参考)。它的实现位于 internal/cmd/createdb.go,会找出配置中database.managed: true的查询集,将 schema 文件(自动剔除回滚语句)作为迁移交给dbmanager建库,并使用sqlc_createdb_<时间戳>作为前缀,最终把新库的 URI 打印到标准输出。它常被用于在sqlc vetsqlc verify等流程之外手动调试分析环境。

迁移后的验证与日常使用

完成sqlc generate后,建议按以下顺序验证迁移结果:

  1. 确认代码生成正常sqlc generate无报错,且生成的*.sql.go文件类型准确;
  2. 运行 vet 检查sqlc vet会在 managed database 上执行依赖真实连接的 lint 规则(如内置的sqlc/db-prepare,它会对每条查询做真实 prepare 以验证 SQL 合法性)。从 internal/cmd/vet.go 可以看到,sqlc vet同样通过dbmanager.NewClient(c.Conf.Servers)走 managed 建库链路,与sqlc generate共用同一套基础设施;
  3. 检查数据库服务器\l(PostgreSQL)或SHOW DATABASES;(MySQL)可以看到sqlc_managed_*前缀的分析库已被创建,说明配置生效。

如果你的 lint 规则需要真实连接但尚未配置任何规则,推荐先启用内置规则sqlc/db-prepare,最小配置如下(来自 托管数据库指南):

version: '2' servers: - engine: postgresql uri: "postgres://localhost:5432/postgres?sslmode=disable" sql: - schema: schema.sql queries: query.sql engine: postgresql database: managed: true rules: - sqlc/db-prepare

常见问题与注意事项

  • 连接串格式mysql://localhost:3306这类 URI 只指定了主机与端口;若数据库要求认证,需在 URI 中补齐用户名密码,例如mysql://root:mysecretpassword@localhost:3306/dinotest。PostgreSQL 建议显式带上?sslmode=disable,避免本机 TLS 协商失败。
  • 引擎支持范围:managed 自动建库目前只支持 MySQL 与 PostgreSQL。如果你的查询集使用 SQLite 等其他引擎,即使配置了servers也不会走 managed 链路。
  • 报错no PostgreSQL database server found:说明没有在servers中找到与查询集引擎匹配的条目。请检查serversengine字段与查询集engine是否一致。
  • 报错unsupported engine:查询集引擎不是mysql/postgresql,见 internal/dbmanager/client.go。
  • 调试连接行为SQLCDEBUG=databases=managed可以强制禁用非 managed 的直连(仅允许 managed 数据库连接),用于排查连接来源问题;相关逻辑见 internal/cmd/vet.go。更多调试开关可参考 环境变量参考。
  • 清理分析库sqlc_managed_*数据库由 sqlc 按需复用(名称由 schema 哈希决定),一般无需手动清理;如需彻底重建,可在服务器上手动删除对应数据库后重新sqlc generate
  • sqlc verify的关系sqlc verify(对比云端归档查询集与本地结果)同样使用dbmanager.NewClient(conf.Servers)复用本地服务器(见 internal/cmd/verify.go),因此迁移后该命令也会自动使用本地 managed 数据库。

总结

迁移到本地数据库服务器的本质,是把"云端托管"这一环节替换为"配置servers指向本地运行的 MySQL/PostgreSQL",其余使用方式(managed: truesqlc generate自动建sqlc_managed_前缀数据库、sqlc vetsqlc verify复用分析库)保持不变。完成 Docker Compose 启动数据库、升级 sqlc 至 v1.31.1+、写入servers配置三步之后,你的项目即可完全脱离托管环境,在本地获得同等(甚至更可控)的查询分析能力。

【免费下载链接】sqlcGenerate type-safe code from SQL项目地址: https://gitcode.com/gh_mirrors/sq/sqlc

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

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

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

立即咨询