Staging — 僅供部落格預覽。
跳至主要內容

結構描述 v60 與漸進式遷移

排程中

閱讀時間 7 分鐘 作者 NT²

本機保管箱是裝置上的真正 SQLite 資料庫。當產品推出結構描述 v60 時,上線時期的保管箱必須就地升級——不能因為原始碼裡的 CREATE 語句變了,就強迫清除重建。

結構描述 v60 與漸進式遷移

主張:上線後的結構描述升級必須就地進行

NT² Vault 把每個保管箱的權威目錄放在本機 SQLite——標題、類別、附件中繼資料、搜尋索引,以及保存身分與解鎖材料的區段存放區。瀏覽器檔案位於 OPFS;桌面殼層則使用原生檔案。無論哪一種,資料庫都不是可丟棄的快取。它是加密承載內容與其周圍關聯鷹架的持久居所。

這種持久性只有在結構描述能演進、卻不把每個使用者保管箱當成開發用暫存區時,才有意義。

我們的主張很直白:**產品上線後,開啟保管箱會從固定的上線基準,漸進式升級其 SQLite 結構描述。**今天這表示戳記在 v59 的保管箱會往前走——從 v60 開始——而不重建資料庫檔案。新建保管箱仍會收到完整的綠地 CREATE 腳本,並戳記為目前的結構描述版本。基準以下的上線前資料庫仍不受支援。結構描述升級是保留使用者資料的產品事件,不是要求人們匯出、刪除、再重來的重建儀式。

結構描述 v60 是具體的公開事實:它是目前的保管箱 SQLite 結構描述版本。更重要的事實是:對產品離開實驗室時就已存在的保管箱,我們如何走到這裡。

約束:壓縮並拒絕在上線前可行;上線後致命

上線前,local-first 產品可以承受一條在正式環境聽起來殘酷的硬規則:若磁碟上的結構描述版本落後於應用程式,就拒絕開啟,並叫開發者重建。歷史遷移步驟可以壓縮成一份綠地 CREATE。代理人不必維護五十條脆弱的 ALTER 路徑。測試驗證的是「以目前版本建立」,而不是「走完每一個古老版本」。對從未承載真實生活資料的預發布保管箱來說,清除並重建是誠實,不是殘忍。

那條政策在真實保管箱進入野外的那天就垮了。

戳記在壓縮基準上的已上線保管箱,前面還有多年的憑證、筆記、附件列與搜尋索引。下一個版本會需要可為空欄位、索引,或小表格調整。若「落後於目前」仍等於「重建」,每一次附加變更都會變成強制遷移劇場:匯出備份、刪除保管箱、再匯入,並希望沒有遺漏。使用者把結構描述演進體驗成資料遺失風險。客服把它當成最後手段的儀式。工程師則把它體驗成對誠實 DDL 出貨的否決權。

還有第二種看起來較軟、實際更糟的失敗模式:靜默清除。開啟保管箱、發現 CREATE 形狀漂移、替換檔案、呈現空列表。把 OPFS 當成可再生成快取的 local-first 產品,會教人們「本機」等於「可消耗」。若密文唯一副本就在你剛替換的檔案裡,零知識也救不了你。

因此約束很尖銳。上線前,壓縮並拒絕過時版本。上線後,上線基準是你可以從中升級的地板,而不是禁止變更的天花板。你需要兩條互補路徑:給空資料庫的綠地,以及給已承載某人生活的資料庫的漸進步驟

地板以下還需要硬界線。不受支援的基準前檔案仍應以關閉方式失敗並走重建路徑——不要試圖從 v1 到壓縮為止復活每一個歷史步驟。那個時代的壓縮仍是最終結果。連續性從上線開始。

設計:綠地 CREATE,加上從 v59 起的有序步驟

保管箱 SQLite 結構描述有一個目前戳記——今天是 60——以及一個上線基準——59。開啟保管箱時讀取已存版本並分支。

flowchart TD
  open[開啟保管箱 SQLite] --> read[讀取結構描述版本]
  read -->|空值 / 空建立路徑| green[套用完整綠地 DDL]
  green --> stampNow[戳記目前版本]
  read -->|版本低於 59| reject[拒絕 — 需要重建]
  read -->|59 到目前減一| loop[套用每個待處理步驟]
  loop --> step[下一版本的附加 DDL]
  step --> stamp[戳記該版本]
  stamp --> loop
  loop -->|已追上| ok[繼續開啟]
  read -->|已是目前| ok
  read -->|新於應用程式| update[拒絕 — 請更新應用程式]

綠地仍是形狀的權威來源。全新保管箱套用完整 CREATE 腳本——資料表、索引、FTS 鷹架、區段存放區——然後戳記目前的結構描述版本。代理人與人必須讓該腳本與現實對齊。漸進步驟不是第二套分歧的結構描述;它們是從昨天的戳記通往今天 CREATE 的橋樑。

漸進式遷移只在已存版本位於或高於上線基準、且仍落後於應用程式時執行。每個待處理版本有一個有序步驟:通常是附加的 ALTER TABLE … ADD COLUMN,並以「若不存在才加入」的紀律套用,讓步驟可以安全重入。每個步驟成功後,資料庫在進入下一步前先戳記該版本。在 v60 應用程式下開啟 v59 保管箱,會套用 v60 步驟並戳記 60。開啟已是 v60 的保管箱,在遷移路徑上是空操作。

基準以下仍拒絕。上線前時代的資料庫不承諾神奇地走完已退役 SQL。復原維持在人能處理的尺度:在產品仍支援時重建,或從可攜備份還原。這種拒絕是刻意的:它讓受支援的遷移面保持有限。

超前於應用程式也拒絕。若保管箱不知何故帶著未來版本戳記,舊用戶端不得發明降級。誠實的訊息是請更新應用程式。結構描述權威屬於理解 CREATE 形狀與步驟登錄的軟體。

第一個上線後步驟——v59 → v60——刻意無聊:在既有對等資料表上加入可為空欄位,讓可選的中樞配對能存放所需內容,而不重寫列。無聊正是重點。執行器比欄位更重要。一旦就地升級能運作,之後每一次升級都以從前一個戳記出發的版本化步驟出貨,並在 CREATE 形狀變更時同步更新綠地 DDL。

這個設計與其他本機耐久選擇並列:保管箱檔案放在 OPFS 而非 IndexedDB 模擬層;SQLite 工作離開 UI 執行緒,讓遷移與查詢不凍結介面;列表 UI 分頁載入,而不是把整個目錄載入記憶體。結構描述演進屬於同一承諾的一部分——資料庫是真實的,真實資料庫需要成熟的升級。

取捨:要維護兩種真相,救援面也更窄

漸進式遷移並非免費。

**我們維護「目前」的兩種表述。**綠地 CREATE 必須描述結構描述 60(以及之後版本)的全新保管箱。每一次升級也需要能把 N − 1 帶到 N、且不摧毀列的步驟。兩者之間的漂移是一類錯誤:CREATE 有欄位但步驟沒有,或步驟假設了 CREATE 從未產生的資料。紀律是強制的——只有在有對應步驟、CREATE 變更時同步綠地、並有文件化版本列時才升級版本號——不是可選的 polish。

**我們放棄復活基準前歷史。**壓縮之後加入的工程師,拿不到 v1–v58 ALTER 腳本博物館。這是維護上的勝利,也是客服面的收斂。仍停在古老上線前建置的使用者會被要求重建,而不是假裝每個實驗室資料庫都該永遠受支援。連續性是從上線開始的產品承諾,不是無限考古學專案。

**我們偏好附加 DDL。**可為空欄位與謹慎回填會保留加密列。破壞性形狀變更——刪除資料表、重寫密文、強制新的信封配置——不是靜默的開啟路徑事件。它們需要明確的產品重大版本與使用者同意。這會讓某些重構變慢。它也阻止「結構描述升級」變成資料遺失的委婉說法。

**我們接受遷移在開啟時執行。**更新 PWA 並解鎖的使用者,可能在保管箱可用前花短暫時間套用步驟。對附加變更來說,成本應保持很小。這仍是我們選擇承擔的成本,而不是為每一個欄位要求人們重建檔案庫。

我們換到的性質,正是 local-first 產品常宣傳、卻很少守住的:你的保管箱檔案能熬過產品自身的演進。密文留在原地。索引留在原地。保存鹽值與驗證碼的區段存放區留在原地。結構描述版本是戳記,不是引爆線。

我們拒絕什麼

**我們拒絕上線後「每次結構描述升級就清除」。**附加演進的預設升級路徑,不得要求刪除 OPFS(或桌面)保管箱檔案。

**我們拒絕在 CREATE 漂移時靜默重建。**把空保管箱呈現成「已更新」,是穿著版本說明外衣的資料遺失錯誤。

**我們拒絕把每一段上線前遷移都復活成受支援表面。**壓縮到 v59 是地板。地板以下以關閉方式失敗並重建——不是盡力重播已退役 SQL。

**我們拒絕在沒有對應漸進步驟時就升級結構描述版本。**只有綠地的升級,會讓上線基準保管箱卡在我們已拒絕的重建牆後面。

**我們拒絕未經同意的破壞性開啟路徑遷移。**刪除使用者資料表、重寫密封承載內容,或丟棄列來「讓 DDL 乾淨」,不得成為解鎖的自動副作用。

**我們拒絕把保管箱資料庫當成可再生成快取。**本機 SQLite 是權威儲存。遷移政策必須聽起來像資料庫產品,而不是暫時的 PWA 實驗。

結語:連續性是 local-first 功能

結構描述 v60 是一個數字。漸進式遷移是讓這個數字對已把保管箱託付給裝置的人變得安全的政策。

綠地 CREATE 讓新建保管箱保持誠實。從 v59 上線基準出發的有序步驟,讓既有保管箱保持連續。拒絕基準前與未來戳記,讓受支援表面保持有限。它們與我們的儲存堆疊說同一件事:保管箱檔案是真實的,因此演進它時不能假裝它可丟棄。

關於該檔案在瀏覽器中的位置,請讀為什麼我們將保管箱的 SQLite 資料庫放在 OPFS,而非 IndexedDB。關於資料庫開啟與遷移時,查詢工作如何離開 UI 執行緒,請讀SQLite 放在 Web Worker 裡,不是選配。關於結構描述長出索引與列之後,列表如何保持快速,請讀永遠不要把整個保管箱載入 Svelte state

若你想要一個本機資料庫能出貨結構描述升級、卻不必走清除儀式的保管箱,請試用 NT² Vault,或到 nt2.me 了解更多。

最後更新 2026-09-30

相關故事