悲観モードでシャードテーブルからデータをマージおよび移行する
このドキュメントでは、悲観的モード (デフォルト モード) のデータ移行 (DM) によって提供されるシャーディング サポート機能を紹介します。この機能を使用すると、上流の MySQL または MariaDB インスタンス内の同じテーブル スキーマを持つテーブルのデータを、下流の TiDB 内の 1 つの同じテーブルにマージして移行できます。
制限
DM には、悲観的モードでのシャーディング DDL の使用に関する次の制限があります。
- 論理シャーディング グループ(1 つの同じダウンストリーム テーブルにマージおよび移行する必要があるすべてのシャード テーブルで構成) の場合、移行を実行するには、シャード テーブルのソースを正確に含む 1 つのタスクを使用するように制限されます。
- 論理シャーディング グループでは、すべての上流シャーディング テーブルで同じ DDL ステートメントを同じ順序で実行する必要があり (スキーマ名とテーブル名は異なる場合があります)、現在の DDL 操作が完全に終了しない限り、次の DDL ステートメントは実行できません。
- たとえば、
column B
を加算する前にtable_1
にcolumn A
加算した場合、column A
加算する前にtable_2
にcolumn B
を加算することはできません。異なる順序で DDL ステートメントを実行することはサポートされていません。
- たとえば、
- シャーディング グループでは、対応する DDL ステートメントをすべての上流のシャーディングされたテーブルで実行する必要があります。
- たとえば、
DM-worker-2
に対応する 1 つ以上のアップストリーム シャード テーブルで DDL ステートメントが実行されない場合、DDL ステートメントを実行した他の DM ワーカーは移行タスクを一時停止し、DM-worker-2
アップストリーム DDL ステートメントを受信するまで待機します。
- たとえば、
- シャーディング グループ移行タスクは
DROP DATABASE
DROP TABLE
していません。- DM-worker の同期ユニットは
DROP TABLE
上流のシャード テーブルのDROP DATABASE
ステートメントを自動的に無視します。
- DM-worker の同期ユニットは
- シャーディング グループ移行タスクは
TRUNCATE TABLE
サポートしていません。- DM-worker の同期ユニットは、上流のシャード テーブルの
TRUNCATE TABLE
ステートメントを自動的に無視します。
- DM-worker の同期ユニットは、上流のシャード テーブルの
- シャーディング グループ移行タスクは
RENAME TABLE
サポートしますが、次の制限があります (オンライン DDL は別のソリューションでサポートされます)。- テーブルの名前を変更できるのは、他のテーブルで使用されていない新しい名前のみです。
- 1 つの
RENAME TABLE
ステートメントには、1 つのRENAME
操作のみを含めることができます。
- シャーディング グループの移行タスクでは、各 DDL ステートメントで 1 つのテーブルのみに対する操作を行う必要があります。
- 異なるシャード テーブルの DML ステートメントを明確なテーブル スキーマでダウンストリームに移行し、後続のシャーディング DDL ステートメントを正しく一致させて移行できるようにするには、増分レプリケーション タスクの開始時点で各シャード テーブルのテーブル スキーマが同じである必要があります。
- テーブルルーティングルールを変更する必要がある場合は、すべてのシャーディング DDL ステートメントの移行が完了するまで待つ必要があります。
- シャーディング DDL ステートメントの移行中に、
dmctl
使用してrouter-rules
を変更するとエラーが報告されます。
- シャーディング DDL ステートメントの移行中に、
- DDL ステートメントが実行されているシャーディング グループに新しいテーブル
CREATE
する必要がある場合は、テーブル スキーマが新しく変更されたテーブル スキーマと同じであることを確認する必要があります。- たとえば、元のテーブル
table_1
とtable_2
はどちらも最初は 2 つの列 (a、b) を持ち、シャーディング DDL 操作後には 3 つの列 (a、b、c) を持つため、移行後に新しく作成されたテーブルにも 3 つの列 (a、b、c) があるはずです。
- たとえば、元のテーブル
- DDL ステートメントを受信した DM ワーカーは、他の DM ワーカーが DDL ステートメントを受信するまでタスクを一時停止するため、データ移行の遅延が増加します。
背景
現在、DM はROW
形式のbinlogを使用して移行タスクROW
実行します。binlogにはテーブル スキーマ情報は含まれません。3binlogを使用してデータを移行する場合、複数のアップストリーム テーブルを同じダウンストリーム テーブルに移行していないと、ダウンストリーム テーブルのテーブル スキーマを更新できるアップストリーム テーブルの DDL 操作は 1 つしか存在しません。5binlogはROW
記述の性質を持つと考えられます。移行プロセス中に、列値とダウンストリーム テーブル スキーマに応じて DML ステートメントを構築できます。
ただし、シャードされたテーブルをマージして移行するプロセスで、アップストリーム テーブルで DDL ステートメントを実行してテーブル スキーマを変更する場合は、列値によって生成された DML ステートメントと実際のダウンストリーム テーブル スキーマ間の不整合を回避するために、DDL ステートメントを移行するための追加の操作を実行する必要があります。
以下に簡単な例を示します。
上記の例では、マージ プロセスが簡略化されており、アップストリームには 2 つの MySQL インスタンスのみが存在し、各インスタンスには 1 つのテーブルのみがあります。移行が開始されると、2 つのシャード テーブルのテーブル スキーマ バージョンはschema V1
としてマークされ、DDL ステートメントを実行した後のテーブル スキーマ バージョンはschema V2
としてマークされます。
ここで、移行プロセスで、2 つの上流のシャード テーブルから受信したbinlogデータが次の時間順序になっていると仮定します。
- 移行が開始されると、DM ワーカーの同期ユニットは、2 つのシャード テーブルから DML イベント
schema V1
を受信します。 t1
では、インスタンス 1 からのシャーディング DDL イベントが受信されます。t2
以降、同期ユニットはインスタンス 1 からschema V2
の DML イベントを受信しますが、インスタンス 2 からはschema V1
の DML イベントを引き続き受信します。t3
では、インスタンス 2 からのシャーディング DDL イベントが受信されます。t4
以降、同期ユニットはインスタンス 2 からもschema V2
の DML イベントを受信します。
移行プロセス中にシャード テーブルの DDL ステートメントが処理されないと仮定します。インスタンス 1 の DDL ステートメントがダウンストリームに移行された後、ダウンストリーム テーブル スキーマはschema V2
に変更されます。ただし、インスタンス 2 の場合、DM ワーカーの同期ユニットは、 t2
からt3
までのschema V1
の DML イベントをまだ受信しています。そのため、 schema V1
の DML ステートメントがダウンストリームに移行されると、DML ステートメントとテーブル スキーマ間の不整合によってエラーが発生し、データを正常に移行できない可能性があります。
原則
このセクションでは、上記の悲観的モードの例に基づいて、DM がシャード テーブルをマージするプロセスで DDL ステートメントを移行する方法を示します。
この例では、 DM-worker-1
MySQL インスタンス 1 からデータを移行し、 DM-worker-2
MySQL インスタンス 2 からデータを移行します。5 DM-master
複数の DM ワーカー間の DDL 移行を調整します。7 DM-worker-1
DDL ステートメントを受信すると、DDL 移行プロセスは次のように簡略化されます。
DM-worker-1
、t1
で MySQL インスタンス 1 から DDL ステートメントを受信し、対応する DDL および DML ステートメントのデータ移行を一時停止し、 DDL 情報をDM-master
に送信します。DM-master
、受信した DDL 情報に基づいてこの DDL ステートメントの移行を調整する必要があることを判断し、この DDL ステートメントのロックを作成し、DDL ロック情報をDM-worker-1
に送り返し、同時にDM-worker-1
このロックの所有者としてマークします。DM-worker-2
、t3
で MySQL インスタンス 2 から DDL ステートメントを受信するまで DML ステートメントの移行を継続し、この DDL ステートメントのデータ移行を一時停止し、 DDL 情報をDM-master
に送信します。DM-master
、受信した DDL 情報に基づいて、この DDL ステートメントのロックがすでに存在すると判断し、ロック情報を直接DM-worker-2
に送信します。- タスク開始時の構成情報、上流MySQLインスタンス内のシャードテーブル情報、およびデプロイメントトポロジ情報に基づいて、
DM-master
、マージされるすべての上流シャードテーブルのこのDDL文を受信したと判断し、DDLロックの所有者(DM-worker-1
)にこのDDL文を下流に移行するように要求します。 DM-worker-1
、ステップ 2 で受信した DDL ロック情報に基づいて DDL ステートメント実行要求を検証し、この DDL ステートメントをダウンストリームに移行し、結果をDM-master
に送信します。この操作が成功した場合、DM-worker-1
後続の DML ステートメント (t2
のbinlogから開始) の移行を続行します。DM-master
、ロック所有者から DDL が正常に実行されたという応答を受け取り、DDL ロックを待機している他のすべての DM ワーカー (DM-worker-2
) にこの DDL ステートメントを無視して、後続の (t4
のbinlogから始まる ) DML ステートメントの移行を続行するように要求します。
複数の DM ワーカー間でのシャーディング DDL 移行を処理する DM の特性は、次のようにまとめることができます。
- タスク構成と DM クラスター展開トポロジ情報に基づいて、DDL 移行を調整するための論理シャーディング グループが
DM-master
に構築されます。グループ メンバーは、移行タスクから分割された各サブタスクを処理する DM ワーカーです。 - 各 DM ワーカーは、 binlogイベントから DDL ステートメントを受信した後、DDL 情報を
DM-master
に送信します。 DM-master
、各 DM ワーカーから受信した DDL 情報とシャーディング グループ情報に基づいて DDL ロックを作成または更新します。- シャーディング グループのすべてのメンバーが同じ特定の DDL ステートメントを受け取った場合、これは上流のシャーディングされたテーブルでの DDL 実行前のすべての DML ステートメントが完全に移行され、この DDL ステートメントを実行できることを示します。その後、DM は後続の DML ステートメントの移行を続行できます。
- テーブルルーターによって変換された後、上流のシャード テーブルの DDL ステートメントは、下流で実行される DDL ステートメントと一致している必要があります。したがって、この DDL ステートメントは DDL 所有者によって 1 回だけ実行される必要があり、他のすべての DM ワーカーはこの DDL ステートメントを無視できます。
上記の例では、各 DM ワーカーに対応するアップストリーム MySQL インスタンスでマージする必要があるシャード テーブルは 1 つだけです。ただし、実際のシナリオでは、複数のシャード スキーマに複数のシャード テーブルがあり、1 つの MySQL インスタンスにマージする必要がある場合があります。このような状況が発生すると、シャーディング DDL 移行の調整がより複雑になります。
1 つの MySQL インスタンスにマージされる 2 つのシャード テーブル ( table_1
とtable_2
があるとします。
データは同じ MySQL インスタンスから取得されるため、すべてのデータは同じbinlogストリームから取得されます。この場合、時間順序は次のようになります。
- 移行が開始されると、DM ワーカーの同期ユニットは、両方のシャード テーブルから DML ステートメント
schema V1
を受け取ります。 t1
では、 DM ワーカーの同期ユニットがtable_1
の DDL ステートメントを受信します。t2
からt3
まで、受信データにはtable_1
からschema V2
の DML 文とtable_2
からschema V1
の DML 文が含まれます。t3
では、 DM ワーカーの同期ユニットがtable_2
の DDL ステートメントを受信します。t4
以降、DM ワーカーの同期ユニットは両方のテーブルからschema V2
の DML ステートメントを受信します。
データ移行中に DDL 文が特に処理されない場合、 table_1
の DDL 文がダウンストリームに移行されてダウンストリーム テーブル スキーマが変更されると、 table_2
からschema V1
の DML 文は正常に移行できません。そのため、単一の DM ワーカー内に、 DM-master
内と同様の論理シャーディング グループが作成されますが、このグループのメンバーは同じアップストリーム MySQL インスタンス内の異なるシャーディング テーブルになります。
しかし、 DM ワーカーがシャーディング グループの移行を自身内で調整する場合、それはDM-master
によって実行されるものと完全に同じではありません。 理由は次のとおりです。
- DM ワーカーが
table_1
の DDL ステートメントを受信すると、移行を一時停止できず、table_2
の後続の DDL ステートメントを取得するためにbinlogの解析を続行する必要があります。つまり、t2
とt3
の間で解析を続行する必要があります。 t2
からt3
の間のbinlog解析プロセス中、シャーディング DDL ステートメントが移行され、正常に実行されるまで、table_1
のschema V2
の DML ステートメントはダウンストリームに移行できません。
DM では、DM ワーカー内で DDL ステートメントをシャーディングする簡略化された移行プロセスは次のとおりです。
t1
でtable_1
の DDL 文を受信すると、 DM ワーカーは DDL 情報とbinlogの現在の位置を記録します。- DM-worker は
t2
からt3
の間のbinlogの解析を続行します。 - DM-worker は、
table_1
に属するschema V2
スキーマの DML ステートメントを無視し、table_2
に属するschema V1
スキーマの DML ステートメントを下流に移行します。 t3
でtable_2
の DDL 文を受信すると、 DM ワーカーは DDL 情報とbinlogの現在の位置を記録します。- 移行タスク構成と上流のスキーマおよびテーブルの情報に基づいて、DM ワーカーは、MySQL インスタンス内のすべてのシャード テーブルの DDL ステートメントが受信されたことを判断し、それらを下流に移行して下流のテーブル スキーマを変更します。
- DM-worker は、新しいbinlogストリームの解析の開始点を、ステップ 1 で保存された位置に設定します。
- DM ワーカーは
t2
からt3
の間のbinlogの解析を再開します。 - DM-worker は、
table_1
に属するschema V2
スキーマの DML ステートメントを下流に移行し、table_2
に属するschema V1
スキーマの DML ステートメントを無視します。 - ステップ 4 で保存されたbinlog の位置を解析した後、DM ワーカーは、ステップ 3 で無視されたすべての DML ステートメントがダウンストリームに再度移行されたと判断します。
- DM-worker は、 binlog の位置
t4
から移行を再開します。
上記の分析から、DM はシャーディング DDL の移行を処理する際に、調整と制御のために主に 2 レベルのシャーディング グループを使用していることがわかります。簡略化されたプロセスは次のとおりです。
- 各 DM ワーカーは、アップストリーム MySQL インスタンス内の複数のシャード テーブルで構成される対応するシャーディング グループの DDL ステートメントの移行を個別に調整します。
- DM ワーカーは、すべてのシャード テーブルの DDL ステートメントを受信すると、DDL 情報を
DM-master
に送信します。 DM-master
、受信した DDL 情報に基づいて、DM ワーカーで構成されたシャーディング グループの DDL 移行を調整します。- すべての DM ワーカーから DDL 情報を受信した後、DDL ロック所有者 (特定の DM ワーカー) に DDL ステートメントの実行を要求
DM-master
ます。 - DDL ロック所有者は DDL 文を実行し、結果を
DM-master
に返します。次に、所有者は DDL 移行の内部調整中に、以前に無視された DML 文の移行を再開します。 DM-master
、所有者が DDL ステートメントを正常に実行したことを確認した後、他のすべての DM ワーカーに移行を続行するように要求します。- 他のすべての DM ワーカーは、DDL 移行の内部調整中に、以前に無視された DML ステートメントの移行を個別に再開します。
- 無視された DML ステートメントの移行が再度完了すると、すべての DM ワーカーが通常の移行プロセスを再開します。