Data Management (DMS) のロックフリーデータ操作言語 (DML) を使用すると、テーブルをロックしたり、データベースパフォーマンスを低下させたりすることなく、大規模なデータセットに対して `UPDATE`、`DELETE`、`INSERT...SELECT` 文を実行できます。DMS エンジンは、対象データを自動的にバッチに分割し、文をバッチごとに実行します。各バッチの間に短い一時停止を挟むことで、プライマリ/セカンダリ間のレプリケーションを保護し、データベースの負荷を軽減します。
背景情報
ビジネスデータが増加するにつれて、履歴データを消去したり、テーブルの大部分を更新したりする必要が頻繁に生じます。一般的な 2 つのアプローチには、どちらも重大なリスクが伴います:
スクリプトを記述してデータを分割する:
LIMIT句を使用して削除や更新をページ分割するのは、よくある間違いです。LIMITをインデックススキャンなしで使用すると、フルテーブルスキャンが強制されるため、テーブルがロックされる可能性があります。分割が正しく実装されていても、バッチ間隔が不適切に調整されていると、プライマリデータベースとセカンダリデータベースの間で深刻なレプリケーションラグが発生する可能性があります。DBA による手動での抽出: 大規模なデータセットを手動で分割するのは、時間がかかり、エラーが発生しやすく、一度開始すると調整が困難です。
上記のリスクに加えて、大規模なテーブルを直接操作する際には、さらに 2 つの障害モードが発生する可能性があります:
影響を与える行が多すぎる単一の SQL ステートメントは、ログエントリ数が上限を超え、ステートメント全体が失敗する原因となる可能性があります。
指定されたインデックスを使用せずに実行された SQL ステートメントは、テーブルロックを引き起こし、データベースの負荷を増大させ、深刻な場合にはビジネスの障害につながる可能性があります。
ロックフリー DML は、DMS 内部でバッチ分割と速度制限を自動化することにより、これらの両方のリスクを排除します。
仕組み
ロックフリー DML は、単一の SQL ステートメントを 3 つのステージで処理します:
データ分割 — DMS エンジンがステートメントを分析し、インデックス範囲に基づいて一致する行を複数のバッチに分割することで、フルテーブルスキャンを回避します。
バッチ実行 — DMS は一度に 1 つのバッチに対してステートメントを実行し、各バッチ中には短時間の行レベルロックのみを保持します。
バッファ間隔 — 各バッチが完了した後、DMS は次のバッチを開始する前に短時間待機します。この間隔により、セカンダリデータベースがレプリケーションに追いつくことができ、プライマリ/セカンダリ間のラグを許容範囲内に保ちます。
メリット
大規模なデータ変更操作中にビジネスに影響を与えません。
データベースパフォーマンスとデータベースストレージへの影響が軽減されます。
大量のデータ変更があっても実行効率が保証されます。
サポートされるデータベース
| データベースエンジン | サポートされるインスタンス |
|---|---|
| MySQL | ApsaraDB RDS for MySQL、PolarDB for MySQL、MyBase for MySQL、PolarDB for Xscale、サードパーティの MySQL データベース |
| PostgreSQL | ApsaraDB RDS for PostgreSQL、PolarDB for PostgreSQL、MyBase for PostgreSQL、サードパーティの PostgreSQL データベース |
| MariaDB | ApsaraDB for MariaDB、サードパーティの MariaDB データベース |
| OceanBase | ApsaraDB for OceanBase (MySQL モード) |
| Oracle 互換 | PolarDB for PostgreSQL (Compatible with Oracle) |
制限事項
サポートされているのは、`UPDATE`、`DELETE`、`INSERT...SELECT` 文のみです。
UPDATE と DELETE
| 制約 | 詳細 |
|---|---|
| テーブル範囲 | 単一テーブルのみ |
| WHERE 句 | 必須です。すべての行を更新または削除するには、WHERE 1=1 |
| サブクエリ | サポートされていません |
| LIMIT 句 | サポートされていません — 手動でのページ分割に LIMIT を使用すると、フルテーブルスキャンが強制され、この機能が防止しようとしているテーブルロックが発生します。 |
INSERT...SELECT
| 制約 | 詳細 |
|---|---|
| SELECT 範囲 | 単一テーブルのみ |
| WHERE 句 | SELECT 句で必須です。すべての行を選択するには、WHERE 1=1 |
| 許可されない句 | LIMIT、ORDER BY、GROUP BY はサポートされていません。 |
利用シーン
履歴データの消去 — 本番テーブルでの読み取りや書き込みをブロックすることなく、不要になった行を削除します。
すべての行の更新 — レプリケーションラグやサービスの中断を引き起こすことなく、テーブル全体に列の更新を適用します。