Skip to content

Latest commit

 

History

History
138 lines (100 loc) · 11.8 KB

File metadata and controls

138 lines (100 loc) · 11.8 KB
title Metadata Lock
summary TiDB のメタデータ ロックの概念、原則、実装の詳細を紹介します。

メタデータロック {#metadata-lock}

このドキュメントでは、TiDB のメタデータ ロックについて説明します。

コンセプト {#concept}

TiDBは、オンライン非同期スキーマ変更アルゴリズムを使用して、メタデータオブジェクトの変更をサポートします。トランザクションが実行されると、トランザクション開始時の対応するメタデータスナップショットが取得されます。トランザクション中にメタデータが変更された場合、データの整合性を確保するために、TiDBはエラーInformation schema is changedを返し、トランザクションはコミットに失敗します。

この問題を解決するため、TiDB v6.3.0 ではオンライン DDL アルゴリズムにメタデータロックが導入されました。ほとんどの DML エラーを回避するために、TiDB はテーブルメタデータの変更時に DML と DDL の優先順位を調整し、古いメタデータを持つ DML がコミットされるまで実行中の DDL を待機させます。

シナリオ {#scenarios}

TiDB のメタデータ ロックは、次のようなすべての DDL ステートメントに適用されます。

メタデータロックを有効にすると、TiDBにおけるDDLタスクの実行にパフォーマンスへの影響が出る可能性があります。この影響を軽減するために、メタデータロックを必要としないシナリオをいくつか以下に示します。

  • 自動コミットが有効になっているクエリはSELECT
  • ステイル読み取りが有効になっています
  • 一時テーブルにアクセスする

使用法 {#usage}

TiDB v6.5.0以降、メタデータロックはデフォルトで有効になります。既存のクラスターをv6.4.0以前からv6.5.0以降にアップグレードすると、TiDBは自動的にメタデータロックを有効にします。メタデータロックを無効にするには、システム変数tidb_enable_metadata_lockOFFに設定します。

インパクト {#impact}

  • DML の場合、メタデータ ロックは実行をブロックせず、デッドロックも発生しません。

  • メタデータ ロックを有効にすると、トランザクション内のメタデータ オブジェクトの情報は最初のアクセス時に決定され、その後は変更されません。

  • DDLの場合、メタデータの状態を変更すると、古いトランザクションによってDDLがブロックされる可能性があります。以下に例を示します。

    セッション1 セッション2
    CREATE TABLE t (a INT);
    INSERT INTO t VALUES(1);
    BEGIN;
    ALTER TABLE t ADD COLUMN b INT;
    SELECT * FROM t;
    (テーブルtの現在のメタデータ バージョンを使用します。5 (a=1, b=NULL)返し、テーブルtをロックします。)
    ALTER TABLE t ADD COLUMN c INT; (セッション 1 によってブロックされています)

    繰り返し可能読み取り分離レベルでは、トランザクションの開始からテーブルのメタデータを決定する時点までの間に、インデックスの追加や列タイプの変更など、データの変更を必要とする DDL が実行されると、DDL は次のようにエラーを返します。

    セッション1 セッション2
    CREATE TABLE t (a INT);
    INSERT INTO t VALUES(1);
    BEGIN;
    ALTER TABLE t ADD INDEX idx(a);
    SELECT * FROM t; (インデックスidxは使用できません)
    COMMIT;
    BEGIN;
    ALTER TABLE t MODIFY COLUMN a CHAR(10);
    SELECT * FROM t; ( ERROR 8028 (HY000): public column a has changedを返す)

可観測性 {#observability}

TiDB v6.3.0 では、現在ブロックされている DDL の情報を取得するのに役立つmysql.tidb_mdl_viewビューが導入されています。

注記:

mysql.tidb_mdl_viewビューを選択するには、 PROCESS権限が必要です。

以下は、テーブルtにインデックスを追加する例です。DDL文ALTER TABLE t ADD INDEX idx(a)があると仮定します。

TABLE mysql.tidb_mdl_view\G
*************************** 1. row ***************************
     job_id: 118
    db_name: test
 table_name: t
      query: ALTER TABLE t ADD COLUMN c INT
 session_id: 1547698182
 start_time: 2025-03-19 09:52:36.509000
SQL_DIGESTS: ["begin","select * from `t`"]
1 row in set (0.00 sec)

上記の出力から、 SESSION ID1547698182あるトランザクションがADD COLUMN DDLをブロックしていることがわかります。7 SQL_DIGEST 、このトランザクションによって実行されたSQL文( ["begin","select * from `t`"]を示しています。ブロックされたDDLの実行を継続するには、次のグローバルKILL文を使用して1547698182トランザクションを強制終了します。

mysql> KILL 1547698182;
Query OK, 0 rows affected (0.00 sec)

トランザクションを強制終了した後、 mysql.tidb_mdl_viewビューを再度選択できます。この時点では、前のトランザクションは出力に表示されません。これは、DDLがブロックされていないことを意味します。

TABLE mysql.tidb_mdl_view\G
Empty set (0.01 sec)

原則 {#principles}

問題の説明 {#description-of-the-issue}

TiDBにおけるDDL操作はオンラインDDLモードです。DDL文の実行中、変更対象オブジェクトのメタデータバージョンは、複数のマイナーバージョン変更を経る可能性があります。オンライン非同期メタデータ変更アルゴリズムは、隣接する2つのマイナーバージョン間の互換性のみを確立します。つまり、2つのバージョン間の操作によって、DDL変更対象のオブジェクトのデータ整合性が損なわれることはありません。

テーブルにインデックスを追加すると、DDL ステートメントの状態は次のように変わります: なし -> 削除のみ、削除のみ -> 書き込みのみ、書き込みのみ -> 書き込み再編成、書き込み再編成 -> パブリック。

次のトランザクションのコミット プロセスは、前述の制約に違反します。

トランザクション トランザクションで使用されるバージョン クラスター内の最新バージョン バージョンの違い
トランザクション1 なし なし 0
トランザクション2 削除のみ 削除のみ 0
トランザクション3 書き込み専用 書き込み専用 0
トランザクション4 なし 書き込み専用 2
txn5 書き込み再編成 書き込み再編成 0
txn6 書き込み専用 書き込み再編成 1
txn7 公共 公共 0

上記の表では、 txn4コミットされたときに使用されるメタデータバージョンは、クラスター内の最新バージョンから 2 バージョン離れています。これにより、データの不整合が発生する可能性があります。

実装の詳細 {#implementation-details}

メタデータロックは、TiDBクラスター内のすべてのトランザクションで使用されるメタデータのバージョン差が最大1バージョン以内であることを保証できます。この目的を達成するために、TiDBは次の2つのルールを実装しています。

  • DMLを実行すると、TiDBはトランザクションコンテキスト内でDMLによってアクセスされたメタデータオブジェクト(テーブル、ビュー、対応するメタデータバージョンなど)を記録します。これらのレコードは、トランザクションがコミットされるとクリーンアップされます。
  • DDL文の状態が変化すると、メタデータの最新バージョンがすべてのTiDBノードにプッシュされます。TiDBノード上でこの状態変化に関連するすべてのトランザクションで使用されるメタデータバージョンと現在のメタデータバージョンの差が2未満の場合、そのTiDBノードはメタデータオブジェクトのメタデータロックを取得したとみなされます。次の状態変化は、クラスター内のすべてのTiDBノードがメタデータオブジェクトのメタデータロックを取得した後にのみ実行できます。