據(jù)庫遷移到本地數(shù)據(jù)庫服務(wù)器:sqlc 的 servers 配置遷移指南)
從托管托管數(shù)據(jù)庫遷移到本地數(shù)據(jù)庫服務(wù)器sqlc 的 servers 配置遷移指南【免費下載鏈接】sqlcGenerate type-safe code from SQL項目地址: https://gitcode.com/gh_mirrors/sq/sqlc從 sqlc 1.27.0 開始managed databases托管數(shù)據(jù)庫功能要求配置文件提供數(shù)據(jù)庫服務(wù)器 URI從 sqlc 1.31.1 起配置中新增了頂層servers映射用于聲明可供查詢分析使用的本地數(shù)據(jù)庫服務(wù)器連接。本指南基于官方遷移文檔完整講解如何將原先依賴托管數(shù)據(jù)庫的 sqlc 項目遷移到本地運行的 MySQL/PostgreSQL 服務(wù)器上涵蓋本地數(shù)據(jù)庫啟動、sqlc 升級、servers配置寫入以及重新生成代碼的全過程并結(jié)合倉庫源碼揭示sqlc_managed_前綴數(shù)據(jù)庫的自動創(chuàng)建機制。背景為什么需要遷移sqlc 的 managed databases 特性自 v1.22.0 引入詳見 托管數(shù)據(jù)庫指南可以讓 sqlc 自動創(chuàng)建只讀數(shù)據(jù)庫為查詢分析query analysis、lint 檢查sqlc vet和驗證sqlc verify提供真實的數(shù)據(jù)庫環(huán)境。相比純靜態(tài)解析連接真實數(shù)據(jù)庫能讓 sqlc 對復(fù)雜查詢生成更準(zhǔn)確的類型安全代碼。從 v1.27.0 開始managed databases 不再使用云端隱式托管而是要求在你的配置文件中顯式提供一個數(shù)據(jù)庫服務(wù)器的 URI連接字符串。這意味著項目必須能訪問到一個真實運行的數(shù)據(jù)庫服務(wù)器。為了讓遷移過程更平滑v1.31.1 又引入了頂層servers配置段允許在配置中聲明一個或多個數(shù)據(jù)庫服務(wù)器供 managed database 邏輯按引擎匹配使用。因此本指南的目標(biāo)是把項目的查詢分析底座從托管遷移到本地運行的真實數(shù)據(jù)庫服務(wù)器整體分三步走在本地啟動數(shù)據(jù)庫服務(wù)器推薦 Docker Compose同時支持 MySQL 與 PostgreSQL升級 sqlc 到 v1.31.1 或更高版本以使用servers配置在配置文件中添加servers映射并重新執(zhí)行sqlc generate。第一步在本地運行一個數(shù)據(jù)庫服務(wù)器本地運行數(shù)據(jù)庫服務(wù)器的方案很多官方遷移指南推薦使用 [Docker Compose]可同時支持 MySQL 和 PostgreSQL如果你在 macOS 上使用 PostgreSQL[Postgres.app] 也是不錯的選擇。說明本指南中的 Docker Compose 配置與端口均以官方遷移文檔為準(zhǔn)請根據(jù)你本機實際占用情況調(diào)整端口映射。使用 Docker Compose 啟動 MySQL創(chuàng)建docker-compose.yml內(nèi)容如下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容器啟動時自動創(chuàng)建的初始數(shù)據(jù)庫名后續(xù) sqlc 會在該服務(wù)器上以sqlc_managed_前綴另建分析用數(shù)據(jù)庫MYSQL_ROOT_PASSWORDroot 用戶的密碼對應(yīng)后續(xù)servers.uri連接串中的密碼部分MYSQL_ROOT_HOST: %允許任意主機通過 root 連接避免容器網(wǎng)絡(luò)下連接被拒3306:3306將容器 3306 端口映射到宿主機servers.uri中的localhost:3306即訪問此端口。使用 Docker Compose 啟動 PostgreSQL若使用 PostgreSQL創(chuàng)建如下docker-compose.ymlversion: 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數(shù)據(jù)庫超級用戶及密碼對應(yīng)連接串中的用戶名和密碼POSTGRES_DB: postgres初始默認數(shù)據(jù)庫5432:5432映射到宿主機的 PostgreSQL 默認端口。啟動服務(wù)docker compose up -d啟動后可通過docker compose ps確認容器狀態(tài)并驗證端口連通性例如mysql -h127.0.0.1 -P3306 -uroot -p或psql -h localhost -p 5432 -U postgres。第二步升級 sqlcservers配置項需要較新的 sqlc 版本。官方遷移指南明確要求必須運行sqlc v1.31.1 或更高版本才能使用servers配置。從倉庫的 變更日志 可以看到相關(guān)演進脈絡(luò)v1.27.0 引入了 Managed databases with any accessible servermanaged databases 開始面向任意可訪問的數(shù)據(jù)庫服務(wù)器同版本還收錄了 Add migration guide for hosted managed databases 的文檔變更正是本指南所對應(yīng)的遷移文檔。升級方式取決于你的安裝渠道如go install、Homebrew、預(yù)編譯二進制等請以官方安裝方式為準(zhǔn)。升級完成后可用sqlc version確認版本號。第三步向配置中添加 serversservers是配置文件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?sslmodedisable從源碼結(jié)構(gòu)看servers對應(yīng) internal/config/config.go 中的Config.Servers []Server字段每個Server包含三個可選字段字段類型說明namestring服務(wù)器名稱便于識別json:name,omitempty可選enginestring引擎標(biāo)識取值如mysql、postgresql可選uristring數(shù)據(jù)庫服務(wù)器連接 URI必填其中引擎常量定義于同一文件的 internal/config/config.gomysql、postgresql、sqlite、clickhouse、googlesql、mssql、duckdb。不過需要注意managed database 的自動建庫邏輯目前只支持 MySQL 與 PostgreSQL詳見下文原理分析。同時使用 MySQL 與 PostgreSQL如果你的項目同時包含 MySQL 和 PostgreSQL 的查詢集可以在servers中并列聲明兩臺服務(wù)器由 managed 客戶端按引擎自動匹配這一點可在 internal/dbmanager/client.go 的源碼中看到遍歷servers列表按server.Engine engine選擇對應(yīng)的URI。結(jié)合managed: true的完整配置示例如下對齊 托管數(shù)據(jù)庫指南 的格式version: 2 servers: - name: mysql engine: mysql uri: mysql://root:mysecretpasswordlocalhost:3306/dinotest - name: postgres engine: postgresql uri: postgres://postgres:mysecretpasswordlocalhost:5432/postgres?sslmodedisable sql: - schema: schema.sql queries: query.sql engine: postgresql database: managed: true gen: go: out: db使用環(huán)境變量推薦連接串中可能包含密碼等敏感信息官方文檔推薦使用${}語法引用環(huán)境變量避免將憑據(jù)硬編碼進配置文件version: 2 servers: - engine: postgresql uri: ${DATABASE_URI} sql: - schema: schema.sql queries: query.sql engine: postgresql database: managed: true從源碼實現(xiàn)看URI 中的${...}占位符會在運行時由 internal/shfmt 的Replacer展開dbmanager客戶端在創(chuàng)建連接前調(diào)用m.replacer.Replace(base)完成替換見 internal/dbmanager/client.go因此密碼等敏感信息可以安全地放在環(huán)境變量中。與 cloud 配置的關(guān)系遷移前配置文件中的cloud.project用于關(guān)聯(lián) sqlc Cloud 項目遷移到本地服務(wù)器后servers與cloud相互獨立、可以并存。如果你不再使用云端服務(wù)保留或移除cloud段均可servers段負責(zé)提供本地連接。若項目未配置servers卻使用了managed: true運行時將報錯no PostgreSQL database server found錯誤文案見 internal/dbmanager/client.go這正是遷移后最常見的問題之一。第四步重新生成代碼完成配置后在項目根目錄執(zhí)行sqlc generate官方遷移指南指出一個帶有sqlc_managed_前綴的數(shù)據(jù)庫會被自動創(chuàng)建并用于查詢分析。sqlc_managed_數(shù)據(jù)庫的底層原理這一行為的實現(xiàn)位于 internal/dbmanager/client.go 的ManagedClient.CreateDatabase其工作流程可以概括為計算數(shù)據(jù)庫名以查詢集 schema 的 SQL 內(nèi)容Migrations為輸入用 FNV-64 哈希生成一個固定 ID再拼接前綴得到數(shù)據(jù)庫名sqlc_managed_hash若調(diào)用方未顯式指定Prefix默認前綴即sqlc_managed見 internal/dbmanager/client.go。由于名稱由 schema 內(nèi)容哈希決定同一 schema 的后續(xù)運行會復(fù)用同名數(shù)據(jù)庫按引擎匹配服務(wù)器遍歷配置中的servers找到與查詢集引擎一致的服務(wù)器 URI當(dāng)前僅放行mysql與postgresql兩種引擎其他引擎直接返回unsupported engine錯誤internal/dbmanager/client.go冪等建庫先查詢pg_database判斷數(shù)據(jù)庫是否已存在不存在則執(zhí)行CREATE DATABASE并通過singleflight保證并發(fā)運行只建一次應(yīng)用 schema連接到新庫逐條執(zhí)行查詢集的 DDLmigrations任一條失敗則DROP DATABASE ... WITH (FORCE)回滾清理internal/dbmanager/client.go。也就是說sqlc generate會自動完成建庫 → 灌入 schema → 用真實數(shù)據(jù)庫做查詢分析 → 按查詢緩存分析結(jié)果的完整鏈路這也是 managed databases 相比純靜態(tài)解析能顯著提升復(fù)雜查詢代碼質(zhì)量的原因。順帶一提sqlc createdb倉庫還提供了sqlc createdb命令Create an ephemeral database見 CLI 參考。它的實現(xiàn)位于 internal/cmd/createdb.go會找出配置中database.managed: true的查詢集將 schema 文件自動剔除回滾語句作為遷移交給dbmanager建庫并使用sqlc_createdb_時間戳作為前綴最終把新庫的 URI 打印到標(biāo)準(zhǔn)輸出。它常被用于在sqlc vet、sqlc verify等流程之外手動調(diào)試分析環(huán)境。遷移后的驗證與日常使用完成sqlc generate后建議按以下順序驗證遷移結(jié)果確認代碼生成正常sqlc generate無報錯且生成的*.sql.go文件類型準(zhǔn)確運行 vet 檢查sqlc vet會在 managed database 上執(zhí)行依賴真實連接的 lint 規(guī)則如內(nèi)置的sqlc/db-prepare它會對每條查詢做真實 prepare 以驗證 SQL 合法性。從 internal/cmd/vet.go 可以看到sqlc vet同樣通過dbmanager.NewClient(c.Conf.Servers)走 managed 建庫鏈路與sqlc generate共用同一套基礎(chǔ)設(shè)施檢查數(shù)據(jù)庫服務(wù)器\lPostgreSQL或SHOW DATABASES;MySQL可以看到sqlc_managed_*前綴的分析庫已被創(chuàng)建說明配置生效。如果你的 lint 規(guī)則需要真實連接但尚未配置任何規(guī)則推薦先啟用內(nèi)置規(guī)則sqlc/db-prepare最小配置如下來自 托管數(shù)據(jù)庫指南version: 2 servers: - engine: postgresql uri: postgres://localhost:5432/postgres?sslmodedisable sql: - schema: schema.sql queries: query.sql engine: postgresql database: managed: true rules: - sqlc/db-prepare常見問題與注意事項連接串格式mysql://localhost:3306這類 URI 只指定了主機與端口若數(shù)據(jù)庫要求認證需在 URI 中補齊用戶名密碼例如mysql://root:mysecretpasswordlocalhost:3306/dinotest。PostgreSQL 建議顯式帶上?sslmodedisable避免本機 TLS 協(xié)商失敗。引擎支持范圍managed 自動建庫目前只支持 MySQL 與 PostgreSQL。如果你的查詢集使用 SQLite 等其他引擎即使配置了servers也不會走 managed 鏈路。報錯no PostgreSQL database server found說明沒有在servers中找到與查詢集引擎匹配的條目。請檢查servers中engine字段與查詢集engine是否一致。報錯unsupported engine查詢集引擎不是mysql/postgresql見 internal/dbmanager/client.go。調(diào)試連接行為SQLCDEBUGdatabasesmanaged可以強制禁用非 managed 的直連僅允許 managed 數(shù)據(jù)庫連接用于排查連接來源問題相關(guān)邏輯見 internal/cmd/vet.go。更多調(diào)試開關(guān)可參考 環(huán)境變量參考。清理分析庫sqlc_managed_*數(shù)據(jù)庫由 sqlc 按需復(fù)用名稱由 schema 哈希決定一般無需手動清理如需徹底重建可在服務(wù)器上手動刪除對應(yīng)數(shù)據(jù)庫后重新sqlc generate。與sqlc verify的關(guān)系sqlc verify對比云端歸檔查詢集與本地結(jié)果同樣使用dbmanager.NewClient(conf.Servers)復(fù)用本地服務(wù)器見 internal/cmd/verify.go因此遷移后該命令也會自動使用本地 managed 數(shù)據(jù)庫。總結(jié)遷移到本地數(shù)據(jù)庫服務(wù)器的本質(zhì)是把云端托管這一環(huán)節(jié)替換為配置servers指向本地運行的 MySQL/PostgreSQL其余使用方式managed: true、sqlc generate自動建sqlc_managed_前綴數(shù)據(jù)庫、sqlc vet與sqlc verify復(fù)用分析庫保持不變。完成 Docker Compose 啟動數(shù)據(jù)庫、升級 sqlc 至 v1.31.1、寫入servers配置三步之后你的項目即可完全脫離托管環(huán)境在本地獲得同等甚至更可控的查詢分析能力?!久赓M下載鏈接】sqlcGenerate type-safe code from SQL項目地址: https://gitcode.com/gh_mirrors/sq/sqlc創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考