回答編集履歴

1 2相コミットはDDL文に対しても可能な旨、コメントを追記しました

ariaki

ariaki score 303

2015/10/21 17:32  投稿

他の方も書かれているようにPHPプログラム側では複数DBに対する同一性を保証する事ができません。
しかしPostgreSQLの「2相コミット(2フェーズコミット)」機能を使えばこれを保証する事ができます。
(KatsumiTanakaさんも書かれている機能です)
やり方は以下の通りです。
(1) beginメソッドによってトランザクションを開始する
(2) insert,update,delete等でデータベースに対する更新を実行する
  [2015/10/21 17:32追記]  
  または、alter等でテーブル定義の更新を実行する  
  ※PostgreSQLはalter等のDDL文にもトランザクションが利用できます  
(3) prepare transactionコマンドによって2相コミットを開始する
 例)prepare transaction 'transaction_id_00000001';
(4) 対象となるすべてのDBに対して(1)-(3)を実行する
(5) コミット/ロールバックを確定する
・コミットの場合:commit preparedコマンド
 例) commit prepared 'transaction_id_00000001';
・ロールバックの場合:rollback preparedコマンド
 例) commit prepared 'transaction_id_00000001';
※通常のcommit/rollbackは必要ありません
(6) 対象となるすべてのDBに対して(5)を実行する
※"prepared transaction"を発行されたDBに対しては、
 必ずcommit/rollback処理を行うようPG上で保証してください。
以上で2相コミットの処理は終了です。
以下、commitまでの簡単なサンプルです。
```ここに言語を入力
begin;
insert into employee values (1, 'ariaki', true);
insert into employee values (2, 'foobar', true);
-- [2015/10/21 17:32追記]  
-- トランザクション内で以下のようにDDL文が利用できます  
alter table employee add column joined date not null;  
prepare transaction 'tran20151021164600';
commit prepared 'tran20151021164600';
```
DBのトランザクション中に"prepare transaction"をすることで、
そのトランザクションに名前をつけて「永続化」させる事ができます。
永続化された状態では、例えばプログラムを終了してもトランザクションは
残り続けますので、後からidを元にcommit/rollbackを行う事ができます。
※逆に言うと永続化されたデータは必ず後からcommit/rollbackしないと
保持(行ロック)され続けるので注意してください。
※現在有効なトランザクションid一覧は"pg_prepared_xacts"テーブル内を
selectすることで確認できます。
2相コミットは上述の通りトランザクションロックが掛かりますので、
定期的にトランザクション残を確認する等、運用は十分に注意してください。
それぞれのコマンドはPostgreSQLのマニュアルを参照してください。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る