Upgrade to Pro — share decks privately, control downloads, hide ads and more …

安全なDDLの実行を目指して 〜(その1)取得するMDLの把握〜

Avatar for tom--bo tom--bo
April 09, 2025

安全なDDLの実行を目指して 〜(その1)取得するMDLの把握〜

Avatar for tom--bo

tom--bo

April 09, 2025
Tweet

More Decks by tom--bo

Other Decks in Technology

Transcript

  1. やりたいこと • メタデータロック(MDL)の理解を深めて、DDL実行をより安全 にしたい • 経験則ではなく事前に競合しうる操作を把握したい • 競合しうるMDLがわかれば、そのMDL取得中の処理時間を見積もって 問題ないか判断できそう •

    なぜMDL? • DDLやバックアップ実行時に、並行して実行されるDMLと競合すると 影響範囲が大きくなりがち • pt-osc, gh-ostを使ってもMDLを取らないわけではない • lock_wait_timeoutを下げることで影響度合いの調整はできる
  2. MDLの取得・解放を確認する方法 • プリントデバッグ方式でロギング • コード修正が必要 • 柔軟な出力が可能 • トレースファイルを取得する •

    トレースを有効にすると出力が多すぎる • MDL取得部分はDBUG_TRACEがないのでコード修正が必要 • それぞれの処理のところでgdbで止める • 逐次実行を進めるのは大変
  3. MDLの取得・解放を確認する方法 • プリントデバッグ方式でロギング • コード修正が必要 • 柔軟な出力が可能 • トレースファイルを取得する •

    トレースを有効にすると出力が多すぎる • MDL取得部分はDBUG_TRACEがないのでコード修正が必要 • それぞれの処理のところでgdbで止める • 逐次実行を進めるのは大変
  4. ログメッセージサンプル(1) • SELECT * FROM t1; • SELECT * FROM

    t1 FOR UPDATE; [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t1, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t1 [MyLog] MDL_context::acquire_lock, key_ns: GLOBAL, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_STATEMENT [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t1, type: MDL_SHARED_WRITE, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: GLOBAL, db_name: , name: [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t1
  5. ログメッセージサンプル(2) • UPDATE t1 SET c1 = 2 WHERE id

    = 1; • BEGIN; UPDATE t1 SET c1 = 2 WHERE id = 1; COMMIT; [MyLog] MDL_context::acquire_lock, key_ns: GLOBAL, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_STATEMENT [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t1, type: MDL_SHARED_WRITE, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: COMMIT, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: COMMIT, db_name: , name: [MyLog] MDL_context::release_lock, key_ns: GLOBAL, db_name: , name: [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t1 [MyLog] MDL_context::acquire_lock, key_ns: GLOBAL, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_STATEMENT [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t1, type: MDL_SHARED_WRITE, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: GLOBAL, db_name: , name: // commit [MyLog] MDL_context::acquire_lock, key_ns: COMMIT, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: COMMIT, db_name: , name: [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t1
  6. ログメッセージサンプル(3) • insert into t1 (id,c1,c2) values (17,1,2),(18,1,2); [MyLog] MDL_context::acquire_lock,

    key_ns: GLOBAL, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_STATEMENT [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t1, type: MDL_SHARED_WRITE, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t1, type: MDL_SHARED, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: COMMIT, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: COMMIT, db_name: , name: [MyLog] MDL_context::release_lock, key_ns: GLOBAL, db_name: , name: [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t1 [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t1 [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: innodb_table_stats, type: MDL_SHARED, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: innodb_index_stats, type: MDL_SHARED, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: mysql, name: innodb_index_stats [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: mysql, name: innodb_table_stats [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: innodb_index_stats, type: MDL_SHARED, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: mysql, name: innodb_index_stats [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: innodb_index_stats, type: MDL_SHARED, duration: MDL_TRANSACTION [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: mysql, name: innodb_index_stats
  7. ログメッセージサンプル(4) • alter table t add column c2 int not

    null; [MyLog] MDL_context::acquire_lock, key_ns: GLOBAL, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_STATEMENT [MyLog] MDL_context::acquire_lock, key_ns: BACKUP_LOCK, db_name: , name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: SCHEMA, db_name: d1, name: , type: MDL_INTENTION_EXCLUSIVE, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t, type: MDL_SHARED_UPGRADABLE, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: check_constraints, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: column_type_elements, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: columns, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: foreign_key_column_usage, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: foreign_keys, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: index_column_usage, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: index_partitions, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: indexes, type: MDL_SHARED_READ, duration: MDL_TRANSACTION [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: mysql, name: schemata, type: MDL_SHARED_READ, duration: MDL_TRANSACTION ... [MyLog] MDL_context::upgrade_shared_lock, key_ns: TABLE, db_name: d1, name: t, type: MDL_EXCLUSIVE ... [MyLog] MDL_context::acquire_lock, key_ns: TABLE, db_name: d1, name: t, type: MDL_EXCLUSIVE, duration: MDL_TRANSACTION [MyLog] MDL_context::upgrade_shared_lock, key_ns: TABLE, db_name: d1, name: t, type: MDL_EXCLUSIVE ... [MyLog] MDL_context::release_lock, key_ns: TABLESPACE, db_name: , name: d1/t [MyLog] MDL_context::release_lock, key_ns: TABLE, db_name: d1, name: t [MyLog] MDL_context::release_lock, key_ns: SCHEMA, db_name: d1, name: [MyLog] MDL_context::release_lock, key_ns: BACKUP_LOCK, db_name: , name:
  8. MDLのロックタイプ ロックタイプ 略記 説明 MDL_INTENTION_EXCLUSIVE IX スコープ付きロック用のIXロック、スキーマの削除防止 MDL_SHARED S メタデータのみを参照するため

    MDL_SHARED_HIGH_PRIO SH I_Sなどで排他ロックを待たずに即時取得を可能にする MDL_SHARED_READ SR データの読みを行う場合 MDL_SHARED_WRITE SW データの更新を行う場合 MDL_SHARED_WRITE_LOW_PRIO SWLP 優先度が低いSWロック MDL_SHARED_UPGRADABLE SU あとから排他ロックに昇格可能なロック MDL_SHARED_READ_ONLY SRO 読み取り専用で他の更新をすべてブロックする MDL_SHARED_NO_WRITE SNW データの変更を禁止するためのロック MDL_SHARED_NO_READ_WRITE SNRW データの読み書きをブロックする MDL_EXCLUSIVE X メタデータとデータの両方を変更するときにとる
  9. MDLの期間 • ステートメント、トランザクション、特定期間の3種類 期間 説明 MDL_STATEMENT • ステートメントの実行期間の間ロックする • ステートメントの終了時に自動的に開放される

    MDL_TRANSACTION • トランザクションの実行期間の間ロックする • トランザクションの終了時に開放される MDL_EXPLICIT • 特定の期間ロックする • ステートメントやトランザクションの終了後ものこり、明示的に release_lock()を呼ぶことで開放される
  10. 課題 • 想像以上に1ステートメントで取得するMDLが多い • メタデータロック以外のロックやラッチで処理が詰まることもある • FLUSH TABLES WITH READ

    LOCK vs 実行中のクエリ • yoku825さんブログ • global read lockで待つらしい • バッファープールが大きいMySQL v5.7でDROP DATABASEが詰まった原因 と対策 • DICT_SYS mutexで詰まった例 • メタデータロック以外も同様にプリントデバッグ方式でやれるか?