知識閱讀 - 如何沒有 Downtime 的更新資料庫樣式
在更新資料庫樣式的時候,會不會影響系統造成 Downtime,最重要的就是你的操作是否可以向下相容。 所以區分成兩個:向下相容、不向下相容
Backward-Compatible Operations
- Add a table or a view:新加上 Table 和 View 對於舊的系統並不會有影響,所以不需要做額外的操作。但是要注意,不要在操作還沒完成就部署上新系統,那就會造成問題了。
- Add a column:添加欄位,也沒有舊系統沒有影響。但是要注意是否有
NOT NULL
constraint,因為NOT NULL
constraint,因為過去的資料就都會是空值,如果有預設值的話就還好處理。如果沒有預設值的話,就建議用以下三種方式來添加 constraint- 新增沒有 constraint 的欄位
- 執行 database script 將其初始值填入欄位
- 加上
NOT NULL
constraint
- Remove a column that’s not used by the old and the new version of your application:此操作因為系統都不在使用該欄位,所以也是可以直接處理(當然前提是確定真的不需要了)
- Remove constraints:不影響系統服務的操作
Backward-Incompatible Operations
針對這些操作,通常就是造成無法順利無 Downtime 的更新。會建議使用一些熱門的工具:Flyway 和 Liquibase。
- Rename a column, a table or a view:今天欄位、資料表和視圖的改名,看起來很簡單。但是卻是最常見造成無法向下相容的問題,主要發生在 Rolling update 的時候。因為同時舊系統還在使用舊的地方,新系統又上線,怎麼在更新過程中兩邊的資料可以是同步的。
- Option 1: Sync with database triggers:如果你的資料庫支援 trigger 的話,那這個操作就比較好處理了。
- 新增新欄位並且將舊資料複製過去,新增 Trigger 將新進入的資料同步到新欄位
- 執行 Rolling update
- 刪除舊資料(Column、Table、View)和 Trigger
- Option 2: Sync programmatically:如果你的資料庫不支援 Trigger 的話,那就會建議將系統進入 Read-only 模式,不然可能會在更新過程丟失一些資料。
- 新增新欄位並且將舊資料複製過去
- 確定新系統會從舊欄位讀取和同時寫入到舊欄位和新欄位 - 先稱其為
new1
。因為此時舊系統依舊可以寫入新資料或更新舊資料,所以要確定new1
要可以處理新舊欄位之後就執行 Rolling update - 確保
new1
都更新後,就可以在更新一版只有處理新欄位的系統new2
- 刪除舊資料欄位
- Option 1: Sync with database triggers:如果你的資料庫支援 trigger 的話,那這個操作就比較好處理了。
- Change the data type of a column:基本上的操作跟 Rename 一樣,唯一的差別是需要更改資料型態
- Remove a column or table or view that’s still used by the old version of your application:需要更新系統才有辦法操作刪除