先界定哪些顧客操作可能受影響
資料庫遷移即使語法正確,仍可能令結帳中斷。真正要問的是:顧客提交訂單時,遷移若取得鎖、改寫資料,或某部應用伺服器仍使用舊程式,會發生甚麼事?先寫窄而清楚的變更範圍:要改哪個欄位、限制條件或索引;哪些讀寫會用到它;哪項顧客操作必須保持可用。網店可能要確保可建立訂單、更新付款狀態,或讓客服讀取現有訂單。列出目前及預計資料結構,也列出部署期間可能同時運行的程式版本。審查便會圍繞真實交易,而非泛泛承諾「零停機」。
應查閱目前實際部署的 PostgreSQL 版本文件。不同 ALTER TABLE 操作在鎖定及改寫方面有不同表現。加入沒有約束的新欄位可避免改寫整張表,但變更現有欄位型別通常會改寫資料表及索引,除非符合文件所述例外。一種操作很快,不代表所有 ALTER TABLE 都很快。要在實際運行環境評估資料表大小、寫入量、相依索引及交易持續時間。只有十筆資料的開發副本,不能反映正式環境的大型資料表及長時間交易會造成甚麼影響。
先擴充結構,再切換程式
假設網店想把一個自由文字的送貨備註,拆成「送貨指示」及「只供員工閱讀備註」兩個欄位。若同一次上線便刪除或改名舊欄位,部署期間舊版程式仍可能讀取它,而新版程式已期待新欄位。較穩妥的分階段做法,是先加入可為空的新欄位,再部署能讀舊資料及寫入或推導新值的程式,以受控批次回填舊紀錄,核對具代表性的紀錄後才切換讀取。所有讀寫者均使用新結構之後,才規劃刪除舊欄位。這是一種程式相容設計,並不代表每一步對所有資料表都自動安全。
團隊必須訂明新舊欄位在過渡期不一致時如何處理。若舊版結帳程式只寫原有備註,而新版同時寫兩個欄位,哪一份資料才算準?一種做法是所有程式更新前先以舊欄位為準,並用可重複安全執行的回填程序推導新值;另一種是建立兼容層處理兩個版本。選擇要視乎資料含義及寫入路徑。測試回填重跑及回填期間顧客修改資料的情況;一次性複製若覆蓋較新的送貨指示,可能比暫時留空更糟。應統計未完成遷移的紀錄並檢查例外,不能只看工作是否以成功狀態結束。
索引與限制條件要分開規劃
為新的訂單查詢建立索引,是另一項獨立的營運事件。PostgreSQL 文件指出,一般 CREATE INDEX 在建置期間會阻止該資料表寫入。CREATE INDEX CONCURRENTLY 可讓一般寫入繼續,但工作量較多、可能需時更長、不能放在交易區塊內,而且失敗後可能留下無效索引。如果遷移框架把所有指令包進交易,或遇錯便自動重試,這些限制尤其重要。團隊應查清框架行為、預留資源、觀察進度,並核實新索引有效,才把遷移視為完成。
限制條件亦要獨立規劃。PostgreSQL 指出,為新的檢查條件或外鍵驗證現有紀錄,可能需要大量掃描並影響同期工作。對支援的限制條件,先用 NOT VALID 加入、稍後再用 VALIDATE CONSTRAINT 驗證,可減少即時影響:新寫入或更新的紀錄會被檢查,舊紀錄則在其後驗證。這並不免除清理舊有矛盾資料及決定驗證失敗如何處理的責任。語法、鎖定行為及適用範圍須以實際部署版本及限制類型的文件為準。從其他版本的文章複製一條指令,不能當作驗收測試。
演練實際營運路徑
觸碰正式環境前,應在保護顧客資料私隱的前提下,以接近實際筆數、索引及異常資料的副本演練。量度遷移所需時間、等待鎖的情況,以及建立訂單和客服查詢受到的影響。演練不能完全重現正式流量,因此要訂明受控變更時段及暫停門檻。備份和經測試的還原方法都要準備,但不能把備份本身稱作回滾計劃:整庫還原可能丟失複製之後真實顧客所下的訂單。對只新增結構的變更,仍能理解舊結構的程式回退,可能是較安全的即時措施;涉及刪除或覆蓋資料則須更具體的修復設計。
正式上線時,應監察與顧客操作有關的訊號:訂單提交逾時、資料庫等待鎖、佇列積壓、寫入失敗及錯誤報告。記錄每一步資料結構及程式變更的開始與完成時間,讓操作人員知道系統現時處於哪個狀態。除非容量測試支持,否則不要同時進行大量回填及建立索引。若超過預設門檻,先停止引入下一步變更、保留證據,並在可行時使用已準備的兼容程式版本。「把遷移回滾」太含糊,特別是資料列已被改動,而顧客又在這段時間下了新訂單。
清理舊結構前先證明新結構可靠
上線後,抽查切換前、切換期間及切換後建立的訂單。確認每筆都能顯示和更新、新欄位值符合預期,而且沒有任何寫入者仍依賴舊欄位。檢查未解決的回填例外;若並行建立索引失敗,亦要查看資料庫是否留下無效索引。然後把清理舊結構排成另一項可審查的變更,另行考慮回復方法。PostgreSQL 刪除舊欄位或許很快,但仍會令讀取該欄位的程式失效,而且未必即時收回磁碟空間。只有業務及技術證據均支持時,才進行清理。
負責人應要求一份簡短的上線紀錄:對實際資料庫版本執行的具體操作、接近真實情況的演練證據、新舊程式並行時的兼容規則、顧客交易的觀察結果,以及異常處理方法。供應商或內部工程師可提出具體指令,但公司本身要明白何時應暫停,以及如何保護期間的新訂單。目標是有清晰狀態、可被觀察的受控變更,而不是保證所有資料結構修改都完全沒有中斷。分清這一點,下次變更會較易規劃,客服遇到顧客反映問題時亦能得到明確說法。
清楚界定繼續或暫停條件
每一步不可逆或成本較高的操作之前,上線負責人都需要明確決定點。以上述送貨備註例子,第一道門檻可以是新欄位已存在、舊版結帳程式仍可使用,而且測試訂單能建立及讀取。之後的門檻可要求回填例外數目達到團隊事先同意的狀態,並抽查真實訂單仍保留顧客指示。實際門檻應按本身流量及服務要求制定;照抄另一間網店的數字只會製造虛假信心。每個決定點都要記下由誰決定繼續、他看到甚麼證據,以及如何暫停而不讓員工猜測。若工作跨越輪班或供應商交接,這尤其重要。
每種失敗都應有具體診斷方向。若遷移一直等待鎖,先找出阻塞的交易,再按正常營運程序決定等待還是改期。若建立索引失敗,重試前要檢查索引是否有效及失敗原因;PostgreSQL 指出,無效的並行索引可能留在系統內並增加寫入負擔。若驗證發現舊有錯誤紀錄,應把資料清理與強行啟用限制分開處理。若新版程式寫出錯誤值,就要停止推進,保留期間建立的訂單以便核對。這些分支比一句「還原備份」更有用,因為團隊評估下一步時仍須保護真實顧客活動。
交付前核對
- 具體資料庫操作是否已按實際部署的 PostgreSQL 版本核對?
- 新舊程式並行期間是否都能處理訂單?
- 是否已監察等待鎖、顧客交易、回填例外及索引有效性?


