ロックフリーのデータ定義言語 (DDL) 変更は、スキーマ変更中にテーブルがロックされるのを防ぎます。この機能は、テーブルのロックによるサービス中断を回避し、ネイティブのオンライン DDL で発生する可能性のあるアクティブ/スタンバイリンクのレイテンシーを防ぎます。オフピーク時にロックフリーの変更を送信することをお勧めします。
背景情報
大規模なテーブルのスキーマを変更する場合、テーブルロックのリスクを考慮する必要があります。ロックされたテーブルは書き込み操作を防ぎます。ネイティブの MySQL は、次の機能を提供します。
MySQL 5.5 以前では、DDL は 2 つの実行アルゴリズムを提供します。
Table-Copy: このアルゴリズムは、データを一時テーブルにコピーすることで変更を加えます。このプロセス中、ソーステーブルはロックされ、書き込み操作は許可されません。
In-Place (MySQL 5.5 以降で利用可能): このアルゴリズムは、実行中にデータベースでの読み取りおよび書き込み操作を許可します。ただし、インデックス関連の変更のみをサポートします。
MySQL 5.6 以降では、DDL は Innodb-OnlineDDL も提供します。Innodb-OnlineDDL の詳細については、「Innodb-OnlineDDL」をご参照ください。
この機能は、列の追加、削除、名前変更、インデックスの追加や変更など、幅広い DDL タイプをカバーしています。ただし、列の型の変更、列の長さの変更、文字セットの変更など、一部の一般的な DDL タイプはカバーしていません。
シナリオ
データベーステーブルのスキーマを変更します。
テーブルの文字セットと照合順序を変更するか、タイムゾーンを調整します。
テーブルロックを引き起こさずに OPTIMIZE TABLE 操作を使用して、表領域を再利用し、断片化を減らします。詳細については、「ロックフリーのスキーマ変更を使用して断片化された領域を再利用する」をご参照ください。
サポートされるデータベースタイプ
RDS for MySQL、PolarDB for MySQL、MyBase for MySQL、およびその他の自己管理 MySQL データベース。
特徴
ネイティブのデータベース機能と比較して、DMS のロックフリーのスキーマ変更機能を使用すると、変更の実行速度を制御できます。これにより、アクティブ/スタンバイリンクでのレイテンシーを回避し、データベースパフォーマンスへの影響を最小限に抑え、ネイティブのオンライン DDL がテーブルをロックする多くのシナリオをサポートします。
pt-online-schema-change や OSC などの他のツールと比較して、DMS のロックフリーのスキーマ変更機能はトリガーに依存しません。この機能は、非同期実行中のデータベースへの影響が最小限であり、いつでも安全に中断できます。
DMS のロックフリーのスキーマ変更機能は DTS との互換性が高いです。変更中のテーブルに DTS テーブルレベルのレプリケーションリンクがある場合、DMS のロックフリーのスキーマ変更機能を使用しても DTS レプリケーションは中断されません。
説明DTS レプリケーションリンクは 2020 年 2 月 14 日以降に再起動されている必要があります。
次の表は、ネイティブの MySQL Online DDL と DMS のロックフリーのスキーマ変更機能の機能を比較したものです。
サポートされる項目
MySQL 5.5 以前
MySQL 5.6 以降
DMS ロックフリーのスキーマ変更
列の追加
いいえ
はい
Y
列の削除
いいえ
はい
はい。
列の名前変更
いいえ
はい
はい
インデックスの追加
N
はい
はい。
インデックスの変更
いいえ
はい
はい
デフラグ操作
N
はい
はい
列の型の変更
N
N
はい
列の長さの変更
いいえ
N
はい
文字セットの変更
N
いいえ
はい
文字セットの変換
いいえ
いいえ
Y
タイムゾーン修正操作
N
いいえ
はい。
セカンダリデータベースのレイテンシーの軽減または排除
いいえ
いいえ
はい
いいえ: サポートされていません。
はい: サポートされています
DMS のロックフリーのスキーマ変更機能と他のソリューションとの比較については、「ロックフリーのスキーマ変更ソリューションの比較」をご参照ください。
注意
DMS は、既存のパーティションテーブルのスキーマ変更をサポートします。
ロックフリーのスキーマ変更機能は、単一の変更チケット内で同じデータベース内の複数のテーブルの変更をサポートします。
チケットで変更 SQL を設定するときは、セミコロン (;) を使用して、異なるテーブルの SQL 文を区切ります。
プライマリキーまたは一意キーのみを持つテーブルでロックフリーのスキーマ変更を実行する場合、プライマリキーまたは一意キーを更新しないでください。そうしないと、変更タスクは失敗します。
米国リージョンの DMS はこの機能をサポートしていません。
仕組み
ロックフリーのスキーマ変更チケットを送信すると、DMS は自動的に次の操作を実行して、テーブルをロックせずに変更を完了します。
一時テーブルの作成: DMS は、ソーステーブルと同じスキーマを持つ一時テーブルをターゲットデータベースに作成します。このテーブルはデータのコピーに使用されます。
SQL 構文は
CREATE TABLE tmp_table_name LIKE table_nameです。一時テーブルのスキーマの変更: 一時テーブルのスキーマが指定どおりに変更されます。
SQL 構文は
ALTER TABLE tmp_table_name XXXXです。完全データの同期: ソーステーブルの完全データが一時テーブルに同期されます。
SQL 構文は
INSERT IGNORE INTO tmp_table_name (SELECT %s FROM table_name FORCE INDEX (%s) WHERE XXX LOCK IN SHARE MODE)です。バイナリログファイルの解析と増分データの同期: ソーステーブルからの増分データが一時テーブルに同期されます。
SQL 構文は
UPDATE/INSERT/DELETE tmp_table_nameです。テーブルの切り替え: ソーステーブルはバックアップとして名前が変更され、一時テーブルがソーステーブルを置き換えます。
SQL 構文は
RENAME TABLE table_name to old_tmp_table_name, tmp_table_name to table_nameです。
tmp_table_name は一時テーブル名の例です。実際の一次テーブル名は、ロックフリー変更のタスク進捗セクションで確認できます。詳細については、「ロックフリー変更の進捗状況の表示」をご参照ください。
次の一覧は、一時テーブル名のフォーマットを説明しています。
データテーブル: `tp_{Change_ID}_ogt_{Source_Table_Name}`、`tp_{Change_ID}_g_{Source_Table_Name}`
ハートビートテーブル: `tp_{Change_ID}_ogl_{Source_Table_Name}`、`tp_{Change_ID}_l_{Source_Table_Name}`
切り替え前の補助テーブルと切り替え後のソーステーブル: `tp_{Change_ID}_del_{Source_Table_Name}`、`tp_{Change_ID}_d_{Source_Table_Name}`
テーブルロック検出: `tpa_xxx_xxx`
変更 ID は、内部 DMS エンジンの実行 ID です。チケット番号やタスク番号ではありません。
リファレンス
ロックフリーのスキーマ変更の背景と動作原理を理解したら、次の操作を実行できます。
インスタンスのロックフリーのスキーマ変更機能を有効にします。詳細については、「ロックフリーのスキーマ変更を有効にする」をご参照ください。
ロックフリーのスキーマ変更チケットを送信します。詳細については、「ロックフリー変更チケットを使用してロックフリーのスキーマ変更を実行する」をご参照ください。
(オプション) ロックフリー変更タスクの進捗状況を表示します。詳細については、「ロックフリー変更の進捗状況の表示」をご参照ください。
API 操作を使用して、ロックフリーのスキーマ変更チケットを設定および管理することもできます。
API
説明
この API 操作は、ロックフリー変更チケットを作成するために使用されます。
この API 操作は、実行ステータスや影響を受けたデータ行数など、ロックフリー変更タスクの詳細を取得するために使用されます。
よくある質問
Q: ロックフリーのスキーマ変更はサービスに影響しますか?
A: 通常の状況では、サービスに影響はありません。ただし、プロセスにはデータコピーが含まれるため、インスタンスのパフォーマンスにわずかな影響があります。
Q: ロックフリー変更チケットで CREATE_INDEX を実行してインデックスを追加するとエラーが報告されます。DMS はインデックスの追加をサポートしていませんか?
A: はい、DMS はインデックスの追加をサポートしています。`CREATE_INDEX` でエラーが発生した場合は、`ALTER TABLE` 文などの代替メソッドを使用できます:
ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) ;