オブジェクトを定義するDDL文について、中央管理ノード上でpgx_ddl_target_nodeパラメータに'ALLNODES'を指定して実行することで、クラスタに参加しているすべてのノード上にデータベースオブジェクトを定義できます。
全ノードに対して定義したオブジェクトを、全ノード対象のオブジェクトと言います。
オブジェクトを操作するDDL文の実行対象オブジェクトが、全ノード対象である場合、中央管理ノード上でpgx_ddl_target_nodeパラメータを空、または、'ALLNODES'を指定して実行することで、全ノードに対して該当のDDL文やオブジェクトの操作が実行できます。
例えば、以下のように実行します。
例1:全ノード対象のオブジェクトの定義 SET pgx_ddl_target_node = 'ALLNODES'; CREATE ROLE role_sc; 例2:全ノード対象のオブジェクトの変更 SET pgx_ddl_target_node = ''; //または、SET pgx_ddl_target_node = 'ALLNODES' ALTER ROLE role_sc LOGIN; //role_scは全ノード対象のオブジェクトのため、全ノードに対して実行される。 例3:全ノード対象のオブジェクトの削除 SET pgx_ddl_target_node = ''; //または、SET pgx_ddl_target_node = 'ALLNODES' DROP ROLE role_sc; //role_scは全ノード対象のオブジェクトのため、全ノードに対して実行される。
全ノードに対するDDL文は、基本的には個別ノードに対するDDL文と同じ動きをしますが、各DDL文の一部オプションについては、追加の仕様の定義が必要であるため、その仕様を定義します。
実行対象のDDL文
ALTER, CREATE, DROP系のコマンド
COMMENT
GRANT, REVOKE, REASSIGN OWNED
IMPORT FOREIGN SCHEMA, SELECT INTO
REFRESH MATERIALIZED VIEW
SECURITY LABEL
ANALYZE, CLUSTER, REINDEX, VACUUM, TRUNCATE
注意
TRUNCATEの対象がレプリケーションテーブルの場合、DDL文が全ノードに実行されるわけではありませんが、レプリケーションの仕組みを使って実行されます。
実行対象外のDDL文
以下のSQLコマンドについては、pgx_ddl_target_nodeを'ALLNODES'に設定し、コマンドを実行した場合、中央管理ノードのみに対して実行されます。全ノードに対しては実行されません。
また、特定のコマンドのVERBOSEオプションについては、全ノードに対して実行はできますが、中央管理ノード上で各ノードの出力結果を表示できません。
スケールアウトのシャードとレプリケーションテーブルについては、DDLの一元実行機能としては、全ノードに対しては実行されませんが、それぞれの機能にて、適切なノードに対して処理が行われます。
ALTER SHARD, CREATE SHARD, DROP SHARD, CREATE REPLICATION TABLE
ALTER PGXNODE, CREATE PGXNODE, DROP PGXNODE
ALTER USER MAPPING ... PGXNODE, CREATE USER MAPPING ... PGXNODE, DROP USER MAPPING ... PGXNODE
CREATE FOREIGN TABLE ... PGXNODE
CREATE SUBSCRIPTION ... WITH (create_slot = true)
COPY
LOCK
CHECKPOINT
DECLARE, FETCH, MOVE, CLOSE
DISCARD
PREPARE, EXECUTE, DEALLOCATE
LISTEN, UNLISTEN, NOTIFY
LOAD
PREPARE TRANSACTION, COMMIT PREPARED, ROLLBACK PREPARED
SET, SET CONSTRAINTS, SET ROLE, SET SESSION AUTHORIZATION, SET TRANSACTION, RESET, SHOW
BEGIN, START TRANSACTION, COMMIT, ABORT, ROLLBACK, END
CALL, DO, EXPLAIN
SAVEPOINT, RELEASE SAVEPOINT, ROLL BACK TO SAVEPOINT
CREATE TEMP TABLEのように、一時テーブルを利用する場合
ANALYZE, CLUSTER, VACUUM, REINDEXでVERBOSEオプションがonの意味で指定された場合
以下の例では、COMMIT/ROLLBACKは、すべて中央管理ノードのみで実行されます。
全ノードや個別のデータノードに対して実行されたDDL文は、中央管理ノード上でのCOMMIT/ROLLBACK実行に併せてCOMMIT/ROLLBACKが実行されることに注意してください。
SET pgx_ddl_target_node = ''; BEGIN; CREATE TABLE tblcoord (a int); SET pgx_ddl_target_node = 'ALLNODES'; CREATE TABLE tblallnodes (a int); COMMIT; //tblcoordが中央管理ノード上、tblallnodesが全ノード上でコミットされる
SET pgx_ddl_target_node = ''; BEGIN; CREATE TABLE tblcoord (a int); SET pgx_ddl_target_node = 'ALLNODES'; CREATE TABLE tblallnodes (a int); ROLLBACK; //tblcoordが中央管理ノード上、tblallnodesが全ノード上でロールバックされる。
SET pgx_ddl_target_node = ''; BEGIN; CREATE TABLE tblcoord (a int); SET pgx_ddl_target_node = 'ALLNODES'; CREATE TABLE tblallnodes (a int); SET pgx_ddl_target_node = ''; COMMIT; //tblcoordが中央管理ノード上、tblallnodesが全ノード上でコミットされる。
SET pgx_ddl_target_node = ''; BEGIN; CREATE TABLE tblcoord (a int); SET pgx_ddl_target_node = 'datanode1'; CREATE TABLE tbldn1 (a int); ROLLBACK; //tblcoordが中央管理ノード上、tbldn1がdatanode1上でロールバックされる。
各種オプション指定時の動作
全ノードに対するDDL文の実行時にオプションを指定した場合、以下のように動作します。
一部のノードに同名のオブジェクトが存在する場合でもエラーにはなりません。
同名のオブジェクトが存在しないノードにはオブジェクトを定義し、同名のオブジェクトが存在するノードについては、注意メッセージが発行されます。
なお、中央管理ノードに、すでにオブジェクトが存在した場合、そのオブジェクトが全ノード対象かどうかの値は変更されません。また、中央管理ノードにオブジェクトが存在せず、データノードに、すでにオブジェクトが存在した場合、中央管理ノードには、全ノード対象のオブジェクトが作成されます。今後、中央管理ノード上でそのオブジェクトへの操作は全ノード対象となるため、データノードに、すでに存在していたオブジェクトも操作の対象となることに注意してください。
一部のノード上でオブジェクトが存在しない場合でもエラーにはなりません。
オブジェクトが存在するノードではオブジェクトを変更し、オブジェクトが存在しないノードについては、注意メッセージが発行されます。
また、中央管理ノード以外の一部のデータノードにオブジェクトが定義されている場合、中央管理ノードでpgx_ddl_target_node = 'ALLNODES'とし、ALTER ... IF EXISTSを実行することで、それらのデータノードに定義されたオブジェクトを変更することができます。
一部のノード上でオブジェクトが存在しない場合でもエラーにはなりません。
オブジェクトが存在するノードではオブジェクトを削除し、オブジェクトが存在しないノードについては、注意メッセージが発行されます。
また、中央管理ノード以外の一部のデータノードにオブジェクトが定義されている場合、中央管理ノードでpgx_ddl_target_node = 'ALLNODES'とし、DROP ... IF EXISTSを実行することで、それらのデータノードに定義されたオブジェクトを削除することができます。
全ノード対象のオブジェクトについて、中央管理ノード上とデータノード上で依存関係が異なっていた場合でも、処理を実施します。
DDL文実行に関する共通事項
DDL文実行に関する共通事項として、以下があります。
オブジェクトを操作するDDL文について、操作対象のオブジェクトを複数指定できるDDL文において、全ノード対象のオブジェクトと全ノード対象でないオブジェクトの両方を同時に指定した場合、エラーとなります。両方を指定した状態で、中央管理ノード上のみで実行したい場合は、中央管理ノード上でpgx_ddl_target_node = 'COORDINATOR'とし、実行してください。
DDL文を全ノードに実行する場合、DDL文に指定するオブジェクトはすべて全ノード対象、あるいは全ノードに存在するものを指定してください。そうでない場合、DDL文が実行エラーになります。
各DDL文の動作
個別のDDL文について、上記以外の項目に関する仕様や動作を以下に示します。
設定パラメータの変更は全ノードに対して実行可能です。
ALTER SYSTEMで設定された値は、次回のサーバ設定の再ロードで、またサーバ開始時にのみ変更可能なパラメータについては次回のサーバ再起動で有効になります。再ロード、サーバ再起動は、各ノードにて個別に実施してください。
全ノード対象のロールについて、中央管理ノード上にそのロールに対する共有ユーザーマッピングが自動で作成されている場合があります。その場合、中央管理ノード上でロールを削除する前に、共有ユーザーマッピングを削除してください。共有ユーザーマッピングは、全データノードと、特別なエントリ"ALLNODES"に対して作成されているため、それらをすべて削除する必要があります。以下のように削除してください。
SET pgx_ddl_target_node = 'COORDINATOR'; DROP USER MAPPING FOR ユーザー名 PGXNODE データノード名1; DROP USER MAPPING FOR ユーザー名 PGXNODE データノード名2; ... DROP USER MAPPING FOR ユーザー名 PGXNODE "ALLNODES";
GRANT ... TO role_specification [, ...]/REVOKE ... FROM role_specification [, ...]に指定したrole_specificationが、全ノード対象のロールである場合、全ノードに対してDDL文が実行されます。
例えば、全ノード対象のロールrole_all に対し、中央管理ノード上のみで定義されたPGXNODE datanode1の権限を付与する場合については、上記の点に注意してください。
これを実現するための方法について、以下に例を示します。
SET pgx_ddl_target_node = 'COORDINATOR'; //GRANT文が、中央管理ノード上のみで実行されるようpgx_ddl_target_nodeの値をCOORDINATORに設定する。 GRANT ALL ON PGXNODE datanode1 TO role_all; RESET pgx_ddl_target_node;
設定パラメータによる影響
ノードごとに以下のパラメータの値が異なる場合、ノードごとに実施されるDDLの結果が異なってしまいます。
db_user_namespace
search_path
default_table_access_method
default_tablespace
default_toast_compression
temp_tablespaces
check_function_bodies
この問題を回避するためには、すべてのノード上でこれらのパラメータの値を同じに設定してください。ただし、中央管理ノード上でSETコマンドでパラメータを変更したとしても、それらは全ノードに伝搬されないことに注意してください。
あるいは、search_path, default_table_access_method, default_tablespace, default_toast_compression, temp_tablespacesについては、DDL実行時に特定のオプションの値が未指定の場合のデフォルトの値を決定するパラメータであるため、DDL実行時に特定のオプションの値を指定することで、上記の問題を回避できます。
DDLの一元実行では、データノードに対するDDLの実行時に、DDL実行時の中央管理ノード上でのsearch_pathと同じ値をデータノードへの接続に対し設定し、実行します。
この際、以下のようなDDL文の実行時に、ユーザーの意図した動作にならない可能性があることに注意してください。
SET pgx_ddl_target_node = 'ALLNODES'; CREATE VIEW view AS SELECT * FROM table;
中央管理ノード上のsearch_pathが$user,public
中央管理ノード上のpublicスキーマにのみ、tableが存在
データノード上の$userスキーマとpublicスキーマそれぞれに、tableが存在
上記の例では、中央管理ノードではpublicスキーマのtableを基にviewが作成されるのに対し、データノードでは$userスキーマのtableを基にviewが作成されます。これはユーザーの意図に反したものとなると考えられます。
そうした挙動を避けるためには、実行対象となるオブジェクトに対し、適切なスキーマ名を付与し、DDL文を実行してください。
例えば上記の例に対して、ユーザーの意図通りに実行されるDDL文は、以下のようになります。
CREATE VIEW public.view AS SELECT * FROM public.table;
全ノードに対するDDL文実行の失敗
全ノードに対するDDL文の実行は、基本的には、PostgreSQLの二相コミットを利用して実現します。二相コミットを利用する場合、全ノードに対するDDL文の実行に対して一部のノードで実行に失敗した場合は、全ノードで実行が失敗となります。停止中のノードが存在する場合にも、全ノードに対するDDL文は実行に失敗します。
全ノードに対してオブジェクトを定義したい場合は、停止中のノードを起動させてから全ノードに対するDDL文を実行してください。
トランザクションブロック内で実行できないDDL文については、二相コミットを利用することができないため、DDL文の実行失敗時に全ノードで実行失敗となりません。この場合は、手動で定義情報の修正を行ってください。
定義情報の修正
二相コミットを利用しない全ノードに対するDDL文の実行が失敗した場合は、一部のノードで実行が失敗し、一部のノードで実行が成功した状態になっています。
この場合、全ノードに対して失敗した状態になるように、手動で定義状態の回復を試みてください。または、全ノードに対して成功した状態になるように、エラーの原因を取り除いた後に、DDL文を再実行してください。
どちらの方法が可能かは、実行するDDL文に依存します。
実行結果の確認
DDL文の実行に失敗した場合、失敗したノードとそのエラー内容を返却します。また、手動で対処が必要なノードについては、その対処内容を表示します。失敗したノード、対処が必要なノードすべてについて、エラー内容や対処内容を表示します。
ただし、中央管理ノードのダウンによりDDL文の実行に失敗した場合は、結果が返却されません。
この場合は、全ノードに対する操作が成功したかを確認してください。
CREATE TABLESPACE, CREATE DATABASE
中央管理ノード上でオブジェクトが定義されているかを確認してください。
定義されている場合、全ノードに対する定義が成功しています。
定義されていない場合は、各データノード上でDDL文の実行に成功したかを個別に確認する必要があります。
実行に成功したかを確認するためには、期待通りに定義が成功しているかを確認するコマンドを実行してください。
各データノード上でDDL文の実行に成功したかを個別に確認する必要があります。
実行に成功したかを確認するためには、期待通りに定義が変更されているかを確認するコマンドを実行してください。
中央管理ノード上でオブジェクトが定義されているかを確認してください。
オブジェクトが定義されている場合、全ノード上からのオブジェクト削除に失敗しています。
定義情報の修正方法
CREATE TABLESPACE, CREATE DATABASEは定義情報の修正が必要な場合があります。
対処が必要なノードについて、作成したオブジェクトの削除を行ってください。DDL文の実行失敗時には自動的な対処を試みますが、それが失敗した場合は、手動で行う必要があります。
具体的には、各ノードに対し、DROP文を実行するか、中央管理ノードでpgx_ddl_target_node = 'ALLNODES'として、DROP ... IF EXISTSを実行してください。
ALTER DATABASE SET TABLESPACEは定義情報の修正が必要な場合があります。
全ノードで失敗した状態になるように、実行が成功したノードについて、変更された定義情報を変更前の状態に戻してください。
または、実行失敗のエラーの原因を取り除いた後に、中央管理ノードに対してDDL文を再実行してください。既に定義が変更されたノードに対してDDL文が実行された場合は、同じ変更が再度実施されます。エラーにはなりません。
DROP TABLESPACE,DROP DATABASE,DROP SUBSCRIPTIONは定義情報の修正が必要な場合があります。
全ノードで成功した状態になるように、実行失敗のエラーの原因を取り除いた後に、中央管理ノードに対してDDL文を再実行してください。その際、既に削除されたノードに対してDDL文が実行された場合は、既に削除されましたとの警告が発生します。エラーにはなりません。
全ノードに対するDDL文実行に関する補足
全ノードに対する定義情報について、各ノード上に定義された定義情報を個別に変更することは推奨されません。
個別のノードに対するDDL文の実行により、そのノード上の定義情報を変更することは可能ですが、変更後、その定義情報に関与する、全ノードに対するDDL文の実行が失敗する可能性があります。