據(jù)庫(kù)層完整解析:Drizzle ORM 與 Postgres/PGlite 內(nèi)嵌數(shù)據(jù)庫(kù)遷移指南)
Openship 數(shù)據(jù)庫(kù)層完整解析Drizzle ORM 與 Postgres/PGlite 內(nèi)嵌數(shù)據(jù)庫(kù)遷移指南【免費(fèi)下載鏈接】openshipSelf-hosted deployment platform項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ope/openshipOpenship是一款自托管部署平臺(tái)Self-hosted Deployment Platform而支撐它的全部數(shù)據(jù)能力就是位于 packages/db/ 下的數(shù)據(jù)庫(kù)層。這一層以Drizzle ORM為核心同時(shí)支持兩種數(shù)據(jù)庫(kù)驅(qū)動(dòng)生產(chǎn)級(jí)的Postgres以及零配置即可運(yùn)行的PGlite 內(nèi)嵌數(shù)據(jù)庫(kù)WASM 版 PostgreSQL無(wú)需安裝任何服務(wù)。所有數(shù)據(jù)庫(kù)遷移Migration在應(yīng)用啟動(dòng)時(shí)自動(dòng)執(zhí)行遷移鏈已從0000一路演進(jìn)到0116。本文將帶你快速看懂驅(qū)動(dòng)如何選擇、遷移鏈如何自動(dòng)運(yùn)行、PGlite 如何避免數(shù)據(jù)損壞以及數(shù)據(jù)導(dǎo)出恢復(fù)怎么做。一圖看懂為什么部署平臺(tái)需要「雙驅(qū)動(dòng)」數(shù)據(jù)庫(kù)層上面就是 Openship 的控制臺(tái)界面。界面上的每一個(gè)項(xiàng)目、部署記錄、域名、服務(wù)器和通知背后都對(duì)應(yīng)數(shù)據(jù)庫(kù)中的一張表。Openship 的數(shù)據(jù)庫(kù)層解決了一個(gè)典型矛盾開(kāi)發(fā)者體驗(yàn)希望clone倉(cāng)庫(kù)就能跑起來(lái)不想先裝 Docker 和 Postgres生產(chǎn)部署希望用標(biāo)準(zhǔn)的 Postgres獲得并發(fā)、備份和運(yùn)維工具鏈的完整能力。解決方案就是一套接口兩種驅(qū)動(dòng)場(chǎng)景驅(qū)動(dòng)數(shù)據(jù)存放位置生產(chǎn) / Docker 自托管node-postgres 連接真實(shí) Postgres你的 Postgres 服務(wù)本地開(kāi)發(fā) / 桌面端PGlite 內(nèi)嵌數(shù)據(jù)庫(kù)默認(rèn)~/.openship/data可用PGLITE_DATA_DIR指定選擇邏輯很簡(jiǎn)單配置了DATABASE_URL或POSTGRES_HOST/POSTGRES_PASSWORD等變量就連 Postgres否則自動(dòng)降級(jí)為 PGlite真正做到零配置啟動(dòng)。統(tǒng)一接口上層代碼不關(guān)心底層是哪個(gè)數(shù)據(jù)庫(kù)數(shù)據(jù)庫(kù)客戶端的工廠邏輯集中在 client.ts 中postgresql://開(kāi)頭的連接串 → 創(chuàng)建node-postgres 連接池 Drizzle實(shí)例連接池上限 20見(jiàn) client.ts空或未配置 → 創(chuàng)建PGlite 內(nèi)嵌數(shù)據(jù)庫(kù)實(shí)例。兩種驅(qū)動(dòng)最終都?xì)w一為同一個(gè)Database類型所有倉(cāng)庫(kù)層Repo和服務(wù)拿到的是同一個(gè)接口完全不知道底層跑的是哪種數(shù)據(jù)庫(kù)。這也是 Drizzle ORM 的價(jià)值類型安全 一套查詢語(yǔ)法覆蓋兩種后端。 小細(xì)節(jié)測(cè)試環(huán)境下VITESTPGlite 會(huì)自動(dòng)切換到內(nèi)存模式memory://保證測(cè)試永不污染磁盤上的開(kāi)發(fā)數(shù)據(jù)——見(jiàn) client.ts。遷移鏈解析從 0000 到 0116 的自動(dòng)演進(jìn)Openship 的遷移文件全部存放在 packages/db/drizzle/ 目錄目前已積累117 個(gè)遷移 SQL 文件起點(diǎn)0000_init.sql —— 初始建表近期演進(jìn)示例0084_analytics_daily_rollup.sql分析日匯總、0108_credential.sql憑據(jù)表、0116_domain_ssl_challenge.sql域名 SSL 驗(yàn)證。遷移如何自動(dòng)運(yùn)行無(wú)論使用哪種驅(qū)動(dòng)應(yīng)用啟動(dòng)時(shí)都會(huì)調(diào)用 Drizzle 的migrate()把packages/db/drizzle/目錄里尚未執(zhí)行的遷移按順序、每條一個(gè)事務(wù)地應(yīng)用完——見(jiàn) client.tsPostgres 驅(qū)動(dòng)與 client.tsPGlite 驅(qū)動(dòng)。開(kāi)發(fā)者的日常工作流只需三步修改表定義packages/db/src/schema/下對(duì)應(yīng)文件運(yùn)行db:generate腳本基于 drizzle-kit配置見(jiàn) drizzle.config.ts生成新的遷移 SQL提交遷移文件重啟應(yīng)用——遷移自動(dòng)完成。?? 特別提醒遷移目錄通過(guò)OPENSHIP_MIGRATIONS_DIR環(huán)境變量可被重定向。桌面端 App 是bun build --compile編譯的單體二進(jìn)制SQL 文件不在文件系統(tǒng)里而是作為數(shù)據(jù)資源隨二進(jìn)制一起發(fā)布這個(gè)變量就是為它準(zhǔn)備的。領(lǐng)域化 Schema49 個(gè)文件一個(gè)業(yè)務(wù)域一個(gè)表集合表定義不是一團(tuán)亂麻而是按業(yè)務(wù)域拆分成 packages/db/src/schema/ 下的近 50 個(gè)文件并在 index.ts 統(tǒng)一導(dǎo)出部署核心project.ts、deployment.ts、service.ts網(wǎng)絡(luò)與邊緣domain.ts、route-rule.ts、edge-target-verification.ts基礎(chǔ)設(shè)施servers.ts、server-container-status.ts、server-tunnel.ts商業(yè)化billing.ts、oauth.ts運(yùn)維backup.ts、notification.ts、service-incident.ts以 deployment.ts 為例可以看到典型的 Drizzle 寫法text主鍵帶dep_前綴、外鍵引用 project 和 organization 并配置級(jí)聯(lián)刪除onDelete: cascade、trigger字段記錄部署由 webhook 還是回滾觸發(fā)。所有字段都有清晰的注釋文檔讀 Schema 就像讀 API 文檔。所有數(shù)據(jù)庫(kù)訪問(wèn)都被收口到倉(cāng)庫(kù)層Repos——見(jiàn) packages/db/src/index.ts 的導(dǎo)出注釋“所有 DB 訪問(wèn)都經(jīng)過(guò)這里”。業(yè)務(wù)代碼不直接拼查詢而是調(diào)用createProjectRepo、createDeploymentRepo等工廠這是全項(xiàng)目可測(cè)試性的關(guān)鍵。避坑指南PGlite 單進(jìn)程鎖與 Postgres 啟動(dòng)等待內(nèi)嵌數(shù)據(jù)庫(kù)最大的風(fēng)險(xiǎn)是兩個(gè)進(jìn)程同時(shí)打開(kāi)同一份數(shù)據(jù)導(dǎo)致不可逆損壞。Openship 在這里做了兩重工程保障① PGlite 單實(shí)例文件鎖— 實(shí)現(xiàn)見(jiàn) pglite-lock.ts用原子創(chuàng)建O_EXCL在數(shù)據(jù)目錄旁生成dir.lock鎖文件保證同一時(shí)刻只有一個(gè)進(jìn)程持有數(shù)據(jù)目錄鎖內(nèi)記錄操作系統(tǒng)級(jí)的機(jī)器標(biāo)識(shí)machine-id / MachineGuid區(qū)分「本機(jī)崩潰殘留」和「另一臺(tái)機(jī)器占用」崩潰自愈發(fā)現(xiàn)前一個(gè)進(jìn)程已死亡死 PID立即回收鎖SIGKILL不會(huì)把目錄鎖死鎖文件刻意放在數(shù)據(jù)目錄外部因?yàn)?PGlite 首次初始化拒絕非空目錄。熱重載場(chǎng)景下新進(jìn)程會(huì)最多等待 30 秒讓舊進(jìn)程優(yōu)雅釋放數(shù)據(jù)庫(kù)避免開(kāi)發(fā)時(shí)反復(fù)出現(xiàn) “already using the database” 報(bào)錯(cuò)。② Postgres 就緒等待— 實(shí)現(xiàn)見(jiàn) client.ts啟動(dòng)時(shí)最多等待90 秒每 1 秒重試一次覆蓋宿主重啟后 Postgres 崩潰恢復(fù)的慢啟動(dòng)致命錯(cuò)誤立即失敗而非空等28P01/28000密碼錯(cuò)誤通常是.env與數(shù)據(jù)卷不匹配和3D000數(shù)據(jù)庫(kù)不存在會(huì)立刻拋出可讀的錯(cuò)誤幫你省下幾十分鐘排查時(shí)間連接池掛載了空閑連接錯(cuò)誤監(jiān)聽(tīng)Postgres 重啟不會(huì)讓整個(gè) API 進(jìn)程崩潰退出。 配套工具package.json提供了db:heal-pglite、db:heal-orphans等自愈腳本入口在 scripts/heal-pglite.ts遇到極端異常時(shí)有標(biāo)準(zhǔn)修復(fù)手段。數(shù)據(jù)層能力延伸導(dǎo)出、恢復(fù)與跨實(shí)例遷移除了 CRUDpackages/db/ 還內(nèi)置了一套結(jié)構(gòu)化備份體系核心在 dump.tsdumpDatabase/restoreDatabase整庫(kù)按拓?fù)漤樞驅(qū)С雠c恢復(fù)dumpSubgraph/restoreSubgraph項(xiàng)目級(jí)子圖導(dǎo)出——把單個(gè)項(xiàng)目及其關(guān)聯(lián)數(shù)據(jù)打包帶走用于團(tuán)隊(duì)模式遷移和項(xiàng)目轉(zhuǎn)讓敏感字段自動(dòng)處理加密列ENCRYPTED_COLUMNS在導(dǎo)出時(shí)剝離防止密鑰材料泄露到備份文件。命令行入口同樣齊備db:dump與db:restore兩個(gè)腳本scripts/dump.ts / scripts/restore.ts配合桌面端發(fā)布打包讓「把數(shù)據(jù)從一臺(tái)自托管服務(wù)器搬到另一臺(tái)」成為一條命令的事??焖偕鲜? 分鐘認(rèn)識(shí) Openship 數(shù)據(jù)庫(kù)層如果你想動(dòng)手體驗(yàn)先獲取代碼git clone https://gitcode.com/GitHub_Trending/ope/openship然后按場(chǎng)景二選一零配置模式什么都不配直接啟動(dòng) API——PGlite 會(huì)在~/.openship/data自動(dòng)建庫(kù)并跑完全部 117 條遷移Postgres 模式設(shè)置DATABASE_URL或直接復(fù)用 docker-compose 中的POSTGRES_HOST/POSTGRES_PASSWORD變量名啟動(dòng)時(shí)自動(dòng)連池并執(zhí)行遷移。 關(guān)鍵文件地圖驅(qū)動(dòng)選擇與啟動(dòng)等待packages/db/src/client.tsPGlite 單實(shí)例鎖packages/db/src/pglite-lock.tsPostgres 咨詢鎖跨進(jìn)程串行化packages/db/src/advisory-lock.ts遷移 SQL 目錄packages/db/drizzle/遷移生成配置packages/db/drizzle.config.ts倉(cāng)庫(kù)層出口packages/db/src/repos/總結(jié)Openship 的數(shù)據(jù)庫(kù)層是一套教科書級(jí)的自托管工程實(shí)踐Drizzle ORM提供類型安全的統(tǒng)一接口Postgres 與 PGlite 雙驅(qū)動(dòng)兼顧生產(chǎn)嚴(yán)謹(jǐn)與開(kāi)發(fā)零門檻自動(dòng)遷移鏈讓 schema 演進(jìn)零手工干預(yù)而單實(shí)例鎖、啟動(dòng)等待與結(jié)構(gòu)化備份則把內(nèi)嵌數(shù)據(jù)庫(kù)最常見(jiàn)的坑提前堵死。理解了這一層你就掌握了 Openship 所有項(xiàng)目、部署與計(jì)費(fèi)數(shù)據(jù)的底層脈絡(luò)?!久赓M(fèi)下載鏈接】openshipSelf-hosted deployment platform項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ope/openship創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考