環境與系統升級的核心約束是系統在升級過程中要持續服務客戶。這個約束排除了「關機 → 換版本 → 開機」的簡單路徑,取而代之的操作模式是四個階段:評估新舊版本的差異、在旁邊建一個新環境驗證、把流量分批切過去、確認沒問題後退役舊環境。這四個階段不管升級的對象是 runtime 版本、資料庫引擎、作業系統還是整個平台,框架相同,差異落在每個階段的具體操作與風險點。

Phase 1:差異評估

差異評估的產出是一份 change manifest——列出所有已知的新舊差異、每項的風險等級、以及需要的應對措施。這份清單是後續所有階段的依據:平行環境要驗證清單上的每一項、切換策略要先處理高風險項、退役前要確認清單上的所有相容性問題都已解決。

差異的三個維度

第一個維度是目標本身的變化。版本升級要看 changelog、breaking changes list、deprecated features list。平台遷移要看兩個平台的功能差異(共享主機沒有的 cron 彈性、VPS 有的 SSH 存取)。資料庫升級要看 SQL 語法差異、預設行為變更(如 MySQL 8.0 的 caching_sha2_password 預設認證方式)。

第二個維度是依賴關係。升級 PHP 版本時,所有 Composer 套件都可能受影響;升級 MySQL 時,ORM 的 SQL 生成可能不相容;遷移平台時,原本靠主機面板設定的 cron job 要改用系統 crontab 或雲端排程。依賴關係沒列完整,平行環境的測試就會漏掉受影響的元件。

第三個維度是過渡期的雙版本相容性。升級不是瞬間完成的——在切換的過程中,系統的某些部分跑新版本、某些部分跑舊版本。這段期間兩個版本必須能共存:資料庫的 schema 要同時相容新舊版本的程式碼、API 的回應格式要讓新舊版本的客戶端都能處理、session 格式要能跨版本延續。

風險分級

風險等級定義應對方式範例
向後相容、不需改 code平行環境驗證即可PHP 8.x 的效能改善
需要改 code 但改動明確先改 code、確認新舊版本都能跑deprecated function 替換
行為變更、可能影響商業邏輯需要完整的功能測試 + 人工驗證浮點數精度變更、排序預設值變更
阻塞無法在新版本運作、沒有替代方案必須在升級前解決或決定放棄升級依賴的套件不支援新版本

每一項差異分級後,高風險和阻塞項決定升級的可行性與時程。阻塞項超過團隊能處理的量時,升級可能需要拆成多個階段(先升到中間版本、再升到目標版本)或延後。

時程與管理層報告

差異評估的時程通常佔整個升級的 20-30%——看起來「還沒開始做」但這段時間的產出(change manifest)決定了後面所有階段的範圍。向管理層報告時用 change manifest 的風險分級表:「共 N 項差異,其中 X 項低風險、Y 項中風險、Z 項高風險、W 項阻塞。中高風險項的處理估計 M 天,阻塞項的替代方案評估需要額外 K 天。」

Phase 2:平行環境驗證

平行環境驗證的責任是用事實證明「新版本在跟 production 相同的條件下能正常運作」。它的產出是一份驗證報告——每一項 change manifest 上的差異都標上「已驗證通過 / 有問題待修 / 不影響」。沒有這份報告就切換,等於在賭新版本會正常。

建立平行環境

平行環境跟 production 越相似,驗證結果越可信。理想狀態是完全複製 production 的架構(同規格、同設定、同網路拓撲),只差目標元件的版本不同。成本限制下的折衷是用縮小版(較小的 instance、較少的資料量),但關鍵設定(PHP 模組、MySQL 參數、安全設定)必須跟 production 一致。

資料的處理要特別注意。用 production 的資料副本驗證最可靠(能觸發真實的邊界狀況),但如果資料含 PII,需要先脫敏處理。另一個選項是用 staging 環境的資料,但要確認 staging 的 schema 跟 production 一致——schema drift 會讓驗證結果失真。

驗證清單

驗證項目方法通過標準
應用程式啟動部署到新環境、觀察 log無 fatal error、所有服務啟動成功
自動化測試跑完整測試套件通過率跟舊環境一致
關鍵業務流程人工操作核心流程(登入、下單、金流)每個步驟的結果正確
效能比對同樣的 workload 打新舊環境回應時間差異 < 10%(或可解釋)
相容性問題逐一驗證 change manifest 的中高風險項每項有「通過」或「已修」的紀錄
外部整合第三方 API callback、webhook、email外部服務能正常與新環境互動

平行期的時間長度

平行環境跑多久才能切換?取決於業務週期。如果系統有月結、季結的批次處理,平行環境至少要跑過一次完整週期。電商系統要跑過至少一個促銷活動。沒有明顯週期的系統,一到兩週的平行驗證通常足夠發現主要問題。

Phase 3:分批切換

分批切換的核心原則是不一次切 100%——先把最低風險的流量導到新環境,觀察一段時間確認正常,再逐步增加比例。

切換策略

策略適用環境操作方式回退速度
DNS 權重切換有多組 server 的環境Route 53 weighted routing 或類似機制,逐步調整新舊比例分鐘級(改 DNS 權重)
Blue-green有 load balancer 的環境新舊環境各掛在不同 target group,LB 切換指向秒級(切 target group)
Canary容器化或 serverless 環境新版本只接 5% → 20% → 50% → 100% 流量秒級(調整 weight)
維護窗口共享主機(無 LB)公告停機時間、切換、驗證、恢復服務分鐘級(FTP 上傳舊版)

共享主機通常只能用維護窗口策略——沒有 load balancer 做流量分配、沒有 DNS 權重可調。維護窗口的關鍵是時間規劃:備份(15 分鐘)→ 切換(30 分鐘)→ 驗證(30 分鐘)→ 恢復或回退(15 分鐘),在窗口內必須完成全部步驟,超時就回退。

切換期間的監控

切換開始後要密切觀察的指標:

  • 錯誤率:5xx / 4xx 比例相對於切換前的基線
  • 回應時間:p50 和 p99 相對於基線
  • 業務指標:轉換率、訂單數、付款成功率(如果適用)
  • 外部整合:第三方 callback 是否正常

回退觸發條件

在切換前就定義好回退條件,避免事故發生時還要開會決定要不要退:

  • 錯誤率超過基線的 2 倍持續 5 分鐘 → 回退
  • 核心業務流程失敗(登入、結帳、金流) → 立刻回退
  • 回應時間超過基線的 3 倍持續 10 分鐘 → 回退

回退不是失敗——它是風險控制機制的正常運作。回退後排查問題、修正、重新走 Phase 2 驗證、再嘗試切換。

切換的通知

對象通知時機內容
內部團隊切換前 24 小時 + 切換開始時切換時間、影響範圍、回退計畫
客戶(如有 SLA)切換前 1 週預計維護窗口、預期影響
外部 vendor切換前 1 週endpoint 變更(如有)、IP 變更(如有)

Phase 4:退役舊環境

切換完成後不要立刻刪掉舊環境——保留 1-2 週的冷備。這段時間處理長尾問題:DNS 快取還沒更新的客戶端、排程任務還指向舊 endpoint 的外部系統、舊環境上可能還有未遷移的資料。

退役前的檢查

  • 舊環境的存取 log 是否歸零?(有流量代表還有東西指向它)
  • 所有 cron job 是否都已在新環境運行?
  • 外部系統的 webhook / callback URL 是否都已更新?
  • 舊環境上有沒有需要歸檔的資料?(log、上傳檔案、備份快照)

退役步驟

  1. 停止舊環境的應用服務(但不刪除)
  2. 觀察 1 週——如果有問題可以快速重啟
  3. 匯出需要保留的資料(log、uploaded files)
  4. 刪除舊環境的運算資源(VM、容器)
  5. 保留舊環境的最後一份備份 30 天,作為最後的保險
  6. 清理舊環境的 DNS 記錄、SSL 憑證、IAM 角色

貫穿全程的升級紀律

一次只升一個東西

同時升級 PHP 版本 + 遷移到新主機 + 重構資料庫 schema,出問題時無法判斷是哪個變更造成的。每次升級只改一個主要元件,穩定後再升下一個。如果業務壓力要求一次完成,至少在 Phase 2 的驗證環境裡逐一引入、逐一確認。

每個階段轉換前備份

Phase 1 結束前備份 production 現況、Phase 3 切換前備份、Phase 4 退役前備份。三份備份各自獨立、各自有還原驗證。備份不只是「做了」——要實際測試過還原,確認備份的完整性。

記錄每一步

每個升級操作記錄在 repo 的 changelog 裡:什麼時間、誰做的、改了什麼、觀察到什麼結果。升級出問題時,changelog 是回溯「上一步做了什麼」的唯一依據。

在平行階段就練習回退

不要等到 Phase 3 切換時才第一次嘗試回退。在 Phase 2 的平行環境裡,刻意從新版本切回舊版本一次,確認回退路徑能走通、回退後服務能正常恢復。回退的演練跟升級的驗證同等重要。

跨分類引用