[英]Is this zero-downtime database migration plan viable?
I am pondering about performing a zero-downtime database migration and came up with minimum necessary steps.我正在考虑执行零停机时间的数据库迁移,并提出了最少的必要步骤。
By "migration" I mean any change in the same database that is not backward-compatible such as renaming, splitting or dropping a column. “迁移”是指同一数据库中不向后兼容的任何更改,例如重命名、拆分或删除列。
Since I couldn't find much information elsewhere, I would like to validate my reasoning with someone having hands-on experience with this.由于我在其他地方找不到太多信息,因此我想与有这方面实践经验的人验证我的推理。 Let's imagine we have a capability to perform rolling deployments, otherwise I don't believe that zero downtime DB migration is possible.
假设我们有能力执行滚动部署,否则我不相信零停机时间的数据库迁移是可能的。 So:
所以:
table1.oldColumn
table1.oldColumn
table1.oldColumn
to table1.newColumn
with zero downtimetable1.oldColumn
重命名为table1.newColumn
,停机时间为零Steps:脚步:
Create table1.newColumn
: ALTER TABLE table1 ADD COLUMN newColumn(...)
创建
table1.newColumn
: ALTER TABLE table1 ADD COLUMN newColumn(...)
Gradually deploy V2.逐步部署 V2。 The V2 code contains the following changes:
V2 代码包含以下更改:
SELECT oldColumn FROM table1 WHERE userId = 1001
. SELECT oldColumn FROM table1 WHERE userId = 1001
。 That's because only oldColumn
contains full data for now while newColumn
contains only a subset of itoldColumn
包含完整数据,而newColumn
只包含它的一个子集oldColumn
. oldColumn
复制。 If we don't do that, we will chase constantly changing oldColumn
foreveroldColumn
INSERT INTO table1 (oldColumn, newColumn) VALUES ('abcd', 'abcd')
INSERT INTO table1 (oldColumn, newColumn) VALUES ('abcd', 'abcd')
DELETE FROM table1 WHERE userId = 1001
DELETE FROM table1 WHERE userId = 1001
DELETE FROM table1 WHERE oldColumn = 'xyz'
DELETE FROM table1 WHERE oldColumn = 'xyz'
Now that all new data is always in sync, we still have a diff between oldColumn
and newColumn
.现在所有新数据始终保持同步,
oldColumn
和newColumn
之间仍然存在差异。 In order to liquidate difference between oldColumn
and newColumn
, we run a background script copying values missing in newColumn
from oldColumn
为了消除
oldColumn
和newColumn
之间的差异,我们运行一个后台脚本,从oldColumn
复制newColumn
中缺少的值
Now that columns are in sync, gradually deploy V3.现在列已同步,逐步部署 V3。 V3 code contains the following changes: SELECTs, UPDATEs, INSERTs and DELETEs go to
newColumn
now. V3 代码包含以下更改:SELECT、UPDATE、INSERT 和 DELETE 现在转到
newColumn
。 table1.oldColumn
is not used anymore table1.oldColumn
不再使用
Drop the unused table1.oldColumn
: ALTER table1 DROP COLUMN oldColumn
删除未使用的
table1.oldColumn
: ALTER table1 DROP COLUMN oldColumn
Note: steps 3 and 5 can be performed as part of the database migration during V2 and V3 startup注意:步骤 3 和 5 可以在 V2 和 V3 启动期间作为数据库迁移的一部分执行
Recap:回顾:
newColumn
is empty and all data goes to oldColumn
newColumn
为空,所有数据都转到oldColumn
oldColumn
alongside newColumn
.oldColumn
一起newColumn
。 At this point some data still flows into oldColumn
only (because we are performing a rolling update so not all instances are V2)oldColumn
(因为我们正在执行滚动更新,因此并非所有实例都是 V2)oldColumn
and newColumn
.oldColumn
和newColumn
中流动。 We mirror updates and inserts to keep columns in syncoldColumn
before newColumn
was devised and some data got there from remaining V1 instances that existed during the rolling update.oldColumn
之前将一些数据插入到newColumn
中,并且一些数据是从滚动更新期间存在的剩余 V1 实例中获取的。 We must get rid of this differenceoldColumn
missing in newColumn
gets copied thereoldColumn
中缺少的newColumn
中的数据复制到那里your use of terms is a bit confusing as what you are describing is not "migration" as the term is normally used.您对术语的使用有点令人困惑,因为您所描述的不是通常使用的术语“迁移”。 Also, it is not clear what your requirements are that you've described as needing zero downtime.
此外,不清楚您所描述的需要零停机时间的要求是什么。 Downtime means making something unavailable for a period of time;
停机意味着使某些东西在一段时间内不可用; you can add/drop a column from a table without making that table unavailable to users so the change requires zero downtime - but obviously any query that referenced a dropped column will no longer work.
您可以在不使该表对用户不可用的情况下从表中添加/删除列,因此更改需要零停机时间 - 但显然任何引用已删除列的查询将不再有效。
If you want to change your DB structure without breaking anything then either you need control over everything that accesses the DB (which is unlikely to be possible) and you can deploy the DB change and everything affected by it in one go - or you can protect users from changes by using views that hide the database implementation from them and only allowing the users to access the views.如果您想在不破坏任何内容的情况下更改数据库结构,那么您需要控制访问数据库的所有内容(这不太可能),并且您可以一次性部署数据库更改以及受其影响的所有内容 - 或者您可以保护用户通过使用隐藏数据库实现并只允许用户访问视图的视图来避免更改。
If you make changes that are so fundamental that they cannot be hidden in a view definition change then you probably have no choice but to communicate this change to your users and they will all need to go through a proper SDLC to determine if the change will affect them and to update their code if it does如果您所做的更改非常重要以至于无法隐藏在视图定义更改中,那么您可能别无选择,只能将此更改传达给您的用户,他们都需要通过适当的 SDLC 来确定更改是否会影响他们并更新他们的代码(如果有的话)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.