ロックフリー DDL 変更は、スキーマ変更中のテーブルロックを防止し、ネイティブのオンライン DDL 操作が引き起こすビジネスの中断やレプリケーションラグを回避します。
背景
大きなテーブルでスキーマ変更を実行する際は、テーブルロックによって書き込み操作がブロックされるリスクを考慮する必要があります。
-
MySQL 5.5 以前のバージョンでは、DDL は 2 つの実行アルゴリズムをサポートしています:テーブルコピーとインプレース。
-
テーブルコピー:データを一時テーブルにコピーし、ソーステーブルをロックして、変更が完了するまで書き込みをブロックします。
-
インプレース (MySQL 5.5 以降で利用可能):実行中に読み取りおよび書き込み操作を許可しますが、インデックス関連の操作のみをサポートします。
-
-
MySQL 5.6 以降のバージョンでは、Innodb-OnlineDDL も導入されています。Innodb-OnlineDDL の詳細については、「Innodb-OnlineDDL」をご参照ください。
Innodb-OnlineDDL は、幅広い DDL タイプに対応しています。ただし、列タイプの変更、列長の変更、文字セットの変更など、一般的なタイプの一部はサポートしていません。
ユースケース
-
データベーステーブルのスキーマを変更します。
-
テーブルの文字セットと照合順序を変更するか、タイムゾーンを調整します。
-
領域を再利用して断片化率を削減する
OPTIMIZE TABLE操作からのテーブルロックを回避します。詳細については、「ロックフリー スキーマ変更を使用した領域の断片化解消」をご参照ください。
サポートされているデータベースタイプ
RDS MySQL、PolarDB for MySQL、MyBase for MySQL、およびその他の MySQL 互換データベース。
機能
-
DMS のロックフリー スキーマ変更機能を使用すると、実行速度を制御できるため、レプリケーションラグを防ぎ、データベースパフォーマンスへの影響を最小限に抑えることができます。また、ネイティブのオンライン DDL では通常テーブルがロックされる変更もサポートします。
-
pt-online-schema-change や OSC とは異なり、DMS のロックフリー スキーマ変更機能はトリガーに依存しません。データベースへの影響を最小限に抑えて非同期で実行され、いつでも安全に中断できます。
-
DMS のロックフリー スキーマ変更機能は DTS との互換性が高く、テーブルレベルの DTS レプリケーションリンクを中断しません。
説明DTS レプリケーションリンクは、2020年2月14日以降に再起動されている必要があります。
-
次の表に、ネイティブの MySQL オンライン DDL 機能と DMS ロックフリー スキーマ変更機能の比較を示します。
操作
MySQL 5.5 以前
MySQL 5.6 以降
DMS ロックフリー スキーマ変更
列の追加
❌
✅
✅
列の削除
❌
✅
✅
列の名前変更
❌
✅
✅
インデックスの追加
✅
✅
✅
インデックスの変更
❌
✅
✅
テーブルの断片化解消
❌
✅
✅
列タイプの変更
❌
❌
✅
列長の変更
❌
❌
✅
文字セットの変更
❌
❌
✅
文字セットの変換
❌
❌
✅
タイムゾーンの調整
❌
❌
✅
リードレプリカの遅延の緩和または解消
❌
❌
✅
一意キーの追加
✅
✅
✅
制約の追加
✅
✅
✅
重要DMS のロックフリー スキーマ変更機能を使用して一意キーまたは制約を追加する場合、新しい一意キーまたは制約に違反するソーステーブル内のデータは、一時テーブルへのコピー処理中に MySQL によって自動的に破棄される点にご注意ください。
DMS のロックフリー スキーマ変更機能と他のソリューションの比較については、「ロックフリー スキーマ変更ソリューションの比較」をご参照ください。
注意事項
-
DMS は、既存のパーティションテーブルのスキーマ変更をサポートしています。
-
1 つのロックフリー スキーマ変更チケットで、同じデータベース内の複数のテーブルを変更できます。
チケットの SQL ステートメントを設定する際、異なるテーブルのステートメントをセミコロン (;) で区切ることができます。
-
主キーまたは一意キーがテーブルの唯一のキーである場合、ロックフリー スキーマ変更中にそのキーを更新することはできません。これを試みると、タスクは失敗します。
仕組み
ロックフリー スキーマ変更チケットを送信すると、DMS は自動的に次の手順を実行して、テーブルをロックせずに変更を完了します。
-
一時テーブルを作成します。DMS は、ソーステーブルのスキーマをミラーリングする新しいテーブルを作成します。
SQL 構文は
CREATE TABLE tmp_table_name LIKE table_nameです。 -
一時テーブルのスキーマを変更します。DMS は、要求された DDL 変更を一時テーブルに適用します。
SQL 構文は
ALTER TABLE tmp_table_name XXXXです。 -
全データをコピーします。DMS は、ソーステーブルから一時テーブルにすべてのデータをコピーします。
SQL 構文は
INSERT IGNORE INTO tmp_table_name (SELECT %s FROM table_name FORCE INDEX (%s) WHERE XXX LOCK IN SHARE MODE)です。 -
バイナリログを解析して増分データを同期します。DMS は、ソーステーブルのバイナリログから一時テーブルに継続的な変更を適用します。
SQL 構文は
UPDATE/INSERT/DELETE tmp_table_nameです。 -
テーブルを入れ替えます。DMS は、ソーステーブルをバックアップ名にアトミックに名前変更し、一時テーブルを元のテーブル名に名前変更します。
SQL 構文は
RENAME TABLE table_name to old_tmp_table_name, tmp_table_name to table_nameです。
tmp_table_name は一時テーブル名の例です。ロックフリー スキーマ変更タスクの進行状況エリアで、特定の一時テーブル名を確認できます。詳細については、「ロックフリー スキーマ変更の進行状況の表示」をご参照ください。
一時テーブル名の形式は次のとおりです:
-
データテーブル:tp_{change_ID}_ogt_{original_table_name}、tp_{change_ID}_g_{original_table_name}
-
ハートビートテーブル:tp_{change_ID}_ogl_{original_table_name}、tp_{change_ID}_l_{original_table_name}
-
スイッチオーバー前の補助テーブルおよびスイッチオーバー後の元のテーブル:tp_{change_ID}_del_{original_table_name}、tp_{change_ID}_d_{original_table_name}
-
テーブルロック検出:tpa_xxx_xxx
変更 ID は、DMS 内部エンジンの実行 ID です。チケット ID またはタスク ID ではありません。
関連ドキュメント
-
ロックフリー スキーマ変更を開始するには、次の手順を実行します。
-
インスタンスのロックフリー スキーマ変更機能を有効にします。詳細については、「ロックフリー スキーマ変更の有効化」をご参照ください。
-
ロックフリー スキーマ変更のチケットを送信します。詳細については、「チケットを使用したロックフリー スキーマ変更の実行」をご参照ください。
-
(オプション) ロックフリー スキーマ変更タスクの進行状況を表示します。詳細については、「ロックフリー スキーマ変更の進行状況の表示」をご参照ください。
-
-
API を使用してロックフリー スキーマ変更チケットを設定および管理することもできます。
API
説明
ロックフリー スキーマ変更のチケットを作成します。
タスクの実行ステータスや影響を受けたデータ行数など、ロックフリー スキーマ変更チケットタスクの詳細を取得します。
よくある質問
-
Q:ロックフリー スキーマ変更はサービスに影響しますか。
A:ロックフリー スキーマ変更は通常、サービスに影響しません。ただし、データコピー処理はインスタンスのパフォーマンスに影響を与える可能性があります。
-
Q:ロックフリー スキーマ変更チケットで
CREATE_INDEXを使用してインデックスを追加しようとしたときにエラーが発生しました。DMS はインデックスの追加をサポートしていませんか。A:はい、DMS はインデックスの追加をサポートしています。次の
ALTER TABLEステートメントを実行してインデックスを追加してください。ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) ; -
Q:ロックフリー スキーマ変更チケットで
rename columnを使用して列の名前を変更しようとしたときにエラーが発生しました。DMS は列の名前変更をサポートしていませんか。A:はい、DMS は列の名前変更をサポートしています。次の
ALTER TABLEステートメントを実行して列の名前を変更してください。ALTER TABLE table_name CHANGE COLUMN old_column_name new_column_name datatype;