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