読み取り専用ノード上で実行中の長時間トランザクションがテーブルのメタデータロック (MDL) を保持している場合、プライマリノードでのデータ定義言語 (DDL) 操作は、そのトランザクションが終了するか、replica_lock_wait_timeout(デフォルト:50 秒)がタイムアウトするまでブロックされます。タイムアウトが発生すると、DDL 操作は ERROR 8007 (HY000): Fail to get MDL on replica during DDL synchronize エラーで失敗します。
polar_slave_work_on_nonblock_mdl_mode を ON に設定すると、プライマリノードでの DDL 操作が、読み取り専用ノード上で競合する MDL の解放を待たずに続行されるようになります。
仕組み
PolarDB for MySQL クラスターでは、プライマリノードでの DDL 操作が完了する前に、すべての読み取り専用ノードに対して MDL の同期を行う必要があります。読み取り専用ノード上で実行中の長時間トランザクションが対象テーブルの MDL を保持している場合、そのトランザクションが終了するか replica_lock_wait_timeout がタイムアウトするまで、MDL 同期はブロックされます。
polar_slave_work_on_nonblock_mdl_mode が ON の場合、プライマリノードでの DDL 操作は、読み取り専用ノード上の競合する MDL を待たずに即座に続行されます。ただし、この設定により、プライマリノードで同時実行された DDL 操作によって、読み取り専用ノード上の単一トランザクション内で異なるテーブルスキーマが観測される可能性があります。
このパラメーターは、長時間トランザクションが原因で発生する MDL ブロッキングのみを解消します。LOCK TABLESまたはFLUSH TABLESによるブロッキングは解消されません。これらの MDL は、明示的にUNLOCK TABLESを実行して解放する必要があります。
前提条件
このパラメーターを有効化する前に、クラスターが以下のすべての条件を満たしていることを確認してください。
バージョン要件 — クラスターは以下のいずれかを満たしている必要があります。
PolarDB for MySQL 8.0、リビジョンバージョン 8.0.1.1.23 以降
PolarDB for MySQL 5.7、リビジョンバージョン 5.7.1.0.19 以降
PolarDB for MySQL 5.6、リビジョンバージョン 5.6.1.0.32 以降
クラスターのリビジョンバージョンを確認するには、「エンジンバージョンの照会」をご参照ください。
分離レベル要件 — 読み取り専用ノードのトランザクション分離レベルは Read Committed または Read Uncommitted である必要があります。Repeatable Read または Serializable 分離レベルでは、このパラメーターは効果がありません。
MDL ブロッキングの診断
パラメーターを有効化する前に、ブロッキングの根本原因が長時間トランザクション(LOCK TABLES や FLUSH TABLES ではない)であることを確認してください。このパラメーターは、明示的なテーブルロックによって保持されている MDL を解除できません。
ステップ 1:プライマリノードで — SHOW PROCESSLIST を実行し、State = Wait for syncing with replicas と表示されている行があるかどうかを確認します。該当する行が存在する場合、DDL 操作が読み取り専用ノードでの MDL 同期待ち状態でブロックされています。
SHOW PROCESSLIST;ステップ 2:読み取り専用ノードで — ブロッキングを引き起こしているトランザクションを特定します。
SELECT * FROM information_schema.innodb_log_mdl_slot WHERE slot_state = 'SLOT_ACQUIRING';クエリが行を返す場合、長時間トランザクションが MDL を保持しています。
+---------+----------------+-----------+----------+-----------+
| slot_id | slot_state | slot_name | slot_lsn | thread_id |
+---------+----------------+-----------+----------+-----------+
| 0 | SLOT_ACQUIRING | test/t | 35025648 | thread-0 |
+---------+----------------+-----------+----------+-----------+出力結果に基づく次のステップ:
| 状況 | 対応 |
|---|---|
| クエリが行を返す(長時間トランザクションが確認された) | polar_slave_work_on_nonblock_mdl_mode を有効化して、今後の発生を防止してください。現在ブロックされている DDL を即座に解除するには、出力結果の thread_id を使用して、該当トランザクションを終了します。 |
| クエリが行を返さない | ブロッキングは長時間トランザクションが原因ではありません。LOCK TABLES または FLUSH TABLES 文がアクティブで実行されていないか確認し、UNLOCK TABLES でロックを解放してください。 |
パラメーターの有効化
PolarDB コンソール にログインします。
左上隅で、ご利用のクラスターがデプロイされているリージョンを選択します。
クラスターを見つけ、その ID をクリックします。
左側のナビゲーションウィンドウで、設定と管理 > パラメーター を選択します。
loose_polar_slave_work_on_nonblock_mdl_modeを見つけ、パラメーターの変更 をクリックします。
変更の送信 をクリックします。変更の保存 ダイアログボックスで、OK をクリックします。

制限事項と副作用
| カテゴリ | 詳細 |
|---|---|
| 適用範囲 | 読み取り専用ノードにのみ適用されます。プライマリノードには影響しません。 |
| テーブルロック/フラッシュ | LOCK TABLES または FLUSH TABLES によって保持されている MDL はバイパスできません。これらのロックは UNLOCK TABLES で解放してください。 |
| 並列クエリのタイムアウト | このパラメーターを有効化した後も、読み取り専用ノード上の並列クエリが replica_lock_wait_timeout(デフォルト:50 秒)を超えて実行されると、MDL 同期の失敗が発生する可能性があります。 |
| スキーマの一貫性 | このパラメーターが ON の場合、プライマリノードで同時実行された DDL 操作により、読み取り専用ノード上のトランザクション内で異なるテーブルスキーマが観測される可能性があります。例については、以下のセクションをご参照ください。 |
パラメーターが ON の場合のスキーマ一貫性の動作
polar_slave_work_on_nonblock_mdl_mode が ON の場合、プライマリノードでの DDL 操作は、読み取り専用ノード上で実行中のトランザクションを待たなくなります。その結果、読み取り専用ノード上の単一トランザクション内で、2 種類のテーブルスキーマが観測されることがあります。
| 読み取り専用ノード(セッション 1) | プライマリノード(セッション 2) |
|---|---|
BEGIN; | |
SELECT * FROM test.t; — カラム a のみを返す | |
ALTER TABLE test.t ADD COLUMN b INT; — 即座に成功 | |
SELECT * FROM test.t; — カラム a および b | |
COMMIT; |
セッション 1 の 2 回目の SELECT は更新後のスキーマを返します。これは、セッション 2 の DDL がトランザクションがまだ開いている間に完了したためです。
このパラメーターが OFF(デフォルト)の場合、セッション 2 の DDL はセッション 1 がコミットするか replica_lock_wait_timeout がタイムアウトするまでブロックされ、ERROR 8007 (HY000): Fail to get MDL on replica during DDL synchronize エラーが返されます。
お問い合わせ
DDL 操作についてご質問がある場合は、テクニカルサポートまでお問い合わせください。