DDL locking details#
グローバルDDLロックとグローバルDMLロックの2種類のロックは、PGDでレプリケートされたDDLの正しさを強制します。
グローバルDDLロック#
グローバルDDLロックは、ddl_locking = 'all'
の場合にのみ使用されます。この種類のロックは、各DDLステートメントの実行中にクラスターで他のDDLが実行されないようにします。この動作は、一般的な場合に完全な正しさを保証しますが、多くの単純な場合には厳密すぎます。
PGDは、スキーマ変更が行われるトランザクションで初めてDDL操作のグローバルロックを取得します。これにより、クラスター内のDDL実行トランザクションが効果的にシリアル化されます。つまり、
DDLの実行中は、ノード上の他の接続は、別のテーブルに影響を与える場合でも、別のDDLコマンドを実行できません。
DDL操作のロックを取得するために、 DDLを実行するPGDノードはPGDグループ内の他のノードに接続し、 DDLを実行する排他的権限を付与するように求めます。
ロック要求は通常のレプリケーションストリームによって送信され、ノードは同様にレプリケーションストリームによって応答します。したがって、ノードまたは少なくともノードの大部分が、レプリケーション遅延をほとんど発生せずに実行されることが重要です。そうしないと、ノードがDDLロックを取得するまでに時間がかかる場合があります。ノードの大部分が同意すると、 DDL実行が実行されます。
DDLロックの順序は、Raftプロトコルを使用して決定されます。 1つのノードで実行されたDDLステートメントは、他のすべてのノードで同じシーケンスで実行されます。
DDLを実行しているノードがクラスター内で実行された以前のすべてのDDLの効果を確認したことを確認するために、以前のDDLを実行したノードに追いつくまで待機します。現在のDDLを実行しているノードが、以前のDDLを実行したノードと比較してレプリケーションが遅れている場合、ロックの取得に時間がかかる場合があります。したがって、単一のノード、または他のノードで発生したレプリケーションの変更にほぼ追いついたノードからDDLを実行することをお勧めします。
グローバルDDLロックは、データおよび監視ノードの大部分によって付与される必要があります。ここで、マジョリティは適格ノードのN/2+1です。サブスクライバー専用ノードは参加する資格がありません。
グローバルDMLロック#
グローバルDMLロックまたはリレーションDMLロックとして知られるこの種類のロックは、ddl_locking = all
またはddl_locking = dml
のいずれか、およびDDLステートメントがフライト中のDMLステートメントが失敗する可能性がある場合に使用されます。これらの障害は、一意制約、チェック制約、NOT
NULL制約などの制約を追加または変更するときに発生する可能性があります。リレーションDMLロックは、一度に1つのリレーションにのみ影響します。これらのロックにより、変更がキュー内にあるときにDDLが実行されず、エラーでレプリケーションが停止する可能性があります。
テーブルのグローバルDMLロックを取得するために、 DDLを実行するPGDノードはPGDグループ内の他のすべてのノードに接続し、書き込みに対してテーブルをロックするように依頼し、そのテーブルの保留中の変更がすべてドレインされるまで待機します。すべてのノードが完全に追いつくと、DMLロックの発信者は自由にテーブルのスキーマ変更を実行し、他のノードにレプリケートできます。
グローバルDMLロックは、各ノードのテーブルのEXCLUSIVE LOCKを保持するため、実行中にそのテーブルに対するDML、他のDDL、VACUUM、およびindexコマンドをブロックします。これは、通常EXCLUSIVE LOCK以上を使用しないコマンドにグローバルDMLロックが保持されている場合にも当てはまります。
保留中のDML操作がドレインされるまでに長い時間がかかる場合があり、レプリケーションが現在遅延している場合はさらに長くなります。これは、データの変更とは異なり、行表現と制約に影響を与えるスキーマの変更は、構成されているすべてのノードに到達でき、現在の書き込みレートに適度に追随しているときにのみ実行できることを意味します。ノードがダウンしているときにこのようなDDLコマンドを実行する必要がある場合は、最初にダウンしたノードを構成から削除します。
ロックが付与される前に、資格のあるすべてのデータノードがグローバルDMLロックを付与することに同意する必要があります。 Witnessおよびサブスクライバ専用ノードは参加する資格がありません。
DDLステートメントがレプリケートされない場合、グローバルロックは取得されません。
PGDシステムでのDDLの実行 で説明しているように、 bdr.ddl_locking パラメーターでロック動作を指定します。
ddl_locking = allは、グローバルDDLロックを取得し、必要に応じてリレーションDMLロックを取得します。ddl_locking = leaderは、リーダーベースのグローバルDMLロックを有効にします。ddl_locking = autoは、可能であればleaderを選択し、それ以外の場合はallを選択します。ddl_locking = dmlは、グローバルDDLロックをスキップし、必要に応じてリレーションDMLロックを取得します。ddl_locking = offは、グローバルDDLロックとリレーションDMLロックの両方をスキップします。
一部のPGDファンクションはDDL変更を行います。これらのファンクションには、 DDLロック動作が適用されます。これについては、各ファンクションのドキュメントに記載されています。
したがって、 ddl_locking = dml
は、競合するDDLが他のノードから実行されないことを保証できる場合にのみ安全です。この設定では、グローバルDDLロックのみを必要とするステートメントは、グローバルロックをまったく使用しません。
ddl_locking = off は、
DDLが実行されるデータベースオブジェクトで競合するDDLと競合するDML操作がないことを保証できる場合にのみ安全です。ロックをオフにした後に問題が発生すると、データの進行中の変更が失われる可能性があります。ユーザーアプリケーションチームは、発生した問題を解決する必要があります。
場合によっては、同時に実行されるDDLを適切にシリアル化できる場合があります。これらのシリアル化障害が発生した場合、 DDLが再実行される場合があります。
DDLレプリケーションは、昇格するまでロジカルスタンバイノードでアクティブになりません。
一部のPGD管理機能はDDLのように動作します。つまり、グローバルロックを取得しようとし、 DDLレプリケーションがアクティブな場合、アクションがレプリケートされます。レプリケートファンクションの完全なリストは、 PGD functions that behave like DDL にリストされています。
一時テーブルで実行されるDDLは、グローバルロックを必要としません。
現在のトランザクションで作成されたオブジェクトのALTERまたはDROPには、グローバルDMLロックは必要ありません。
グローバルDDLロックとグローバルDMLロックのモニタリングは Monitoring the Connection Manager に表示されます。