web-dev-qa-db-ja.com

別のサーバーのデータベースのテーブルデータを更新するトリガーを作成する

MySQLでトリガーを作成しています。少し手助けが必要です。

S1とS2の2つの異なるWebサーバー上に2つのWebサイト、2つのデータベース(同じ名前)があります。

これらのデータベースは同じテーブル名を持っています。

両方のWebサイトの両方のユーザーデータを同じにしたい。

したがって、1人のユーザーがS1に登録する場合、そのユーザー登録情報をS2に渡す必要があります。

S1でユーザー登録情報を更新した場合、S2でも同じ情報を更新する必要があります。

S2についても同様です。

トリガーを作成して、S1のデータベースに挿入/更新/削除があるたびに、S2のユーザーテーブルも自動的に更新されるようにするにはどうすればよいですか?.

また、S2のデータベースに挿入/更新/削除があるたびに、S1のユーザーテーブルも自動的に更新されます。

これは可能ですか?いくつか例を挙げていただけますか?

8
mkb

やりたいことを達成するために、トリガーと組み合わせて両方のサーバーで FEDERATED storage engine を使用して、各サーバーが他のサーバーのデータベースを更新できるようにすることができます。

これは、追加の予防策が必要であり、整合性または分離の許容度のどちらがより重要であるかを決定し、他のサーバーが利用できない場合にクエリが失敗することを許可する必要があるため(これはより整合性が高いため)、これは単純にすぐに使用できるソリューションではありません。 )または CONTINUE HANDLER エラー(分離許容値)を抑制します。

しかし、これは極端に簡略化された例です。

各サーバーの構成は同じです。

ローカルユーザーテーブル:

CREATE TABLE user (
  username varchar(64) NOT NULL,
  password varbinary(48) NOT NULL, /* encrypted of course */
  PRIMARY KEY(username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

他のサーバーのユーザーテーブルにフェデレーションされるローカルテーブル。

CREATE TABLE remote_user (
  username varchar(64) NOT NULL,
  password varbinary(48) NOT NULL, /* encrypted of course */
  PRIMARY KEY(username)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8 CONNECTION='mysql://username:pass@the_other_Host:port/schema/user';

一方のサーバーのremote_userから選択すると、もう一方のサーバーからレコードが取得され、そのテーブルで挿入/更新/削除を行うと、他のサーバーのデータが変更されます。

したがって、距離サーバーを更新する目的を達成するトリガーを作成します。それらはBEFOREトリガーとして記述されます。たとえば、他のサーバーに実行できないことを自分自身に実行したくないという考えです。サーバーではなく、ここでは、他のサーバーへの挿入でエラーをスローして、ユーザーをここに作成できないようにします。競合するユーザー名でユーザーをここに作成するのではありません。もちろん、これはあなたがしなければならないトレードオフの決定の1つです。

DELIMITER $$

CREATE TRIGGER user_bi BEFORE INSERT ON user FOR EACH ROW
BEGIN
  INSERT INTO remote_user (username,password) VALUES (NEW.username,NEW.password);
END $$

CREATE TRIGGER user_bu BEFORE UPDATE ON user FOR EACH ROW
BEGIN
  UPDATE remote_user 
     SET username = NEW.username,
         password = NEW.password
   WHERE username = OLD.username;
END $$

CREATE TRIGGER user_bd BEFORE DELETE ON user FOR EACH ROW
BEGIN
  DELETE FROM remote_user
   WHERE username = OLD.username;
END $$

DELIMITER ;

これは完璧なソリューションではなく、高可用性ソリューションでもありません。これは、2つのシステム間の強固な接続に依存しており、InnoDBとトランザクションを使用している場合でも、ターゲットテーブルに対して行うアクションはローカルトランザクションの一部ではないためです。ロールバックできません。

私はFEDERATEDエンジンをかなり使用しています。これは、トリガーによって起動されたフェデレーテッドクエリを使用して外部データソースに外部キー制約を課す1つの状況を含め、私の環境で多くの創造的な目的に役立ちます。ただし、タイムアウト、コーディングエラー、サーバー間ネットワーク/停止/分離イベントなどの予期しない問題が原因で、エンドユーザーがいずれかの種類の問題を経験しているバックエンドプロセスに使用できないバックエンドプロセスに使用を制限しています。このような状況を許容するあなたの能力は、これが適切な解決策であるかどうかの主要な決定要因になります。

もう1つの方法は、マスター/マスターレプリケーションで2つのサーバーを構成することです。このため、各サーバーでdifferentデータベース名を使用する必要があります。これにより、複製されるほとんどのイベントで、2つのサーバーがそれぞれと競合する可能性がなくなります。その他。最悪のシナリオでは、接続が失われたり、レプリケーションエラーが発生したりした場合でも、2つのサイトは独立して実行されているため、再同期して回復できます。構成は次のようになります。

database_a database for site A
database_b database for site B
database_c database for only the shared table(s)

次に、database_aとdatabase_bで:

CREATE ALGORITHM=MERGE SQL SECURITY INVOKER VIEW user AS SELECT * FROM c.user;

MySQLは、database_a.userおよびdatabase_b.userを「実際の」ユーザーテーブルdatabase_c.userのエイリアスとして扱います。そのため、指定されたデータベースを使用する以外にアプリケーションを変更する必要はありません(つまり、設定する必要はありません)。ビューはこの構成ではほとんど透過的に機能するため、ユーザーテーブルが実際には別のスキーマにあることを理解するためです。スキーマにユーザーテーブルに対する外部キーがある場合、実際のベーステーブルdatabase_c.userに対してそれらを宣言します。

すべてを複製するように2つのサーバーを構成しますが、- auto_increment_increment およびauto_increment_offsetテーブルが自動インクリメントを使用している場合、共有テーブルで競合する自動インクリメント値がないように適切に。 (注意、これらの変数はNDBテーブルのみを対象としていますが、正確ではありません)。

このセットアップのもう1つの利点は、2つのサーバーが他のサイトのデータの完全な複製を持ち、サーバーの1つでハードウェア障害からの回復に有利に使用できることです。

11

等しくなければならないのは、多くのテーブルのうちの1つだけです。

したがって、トリガーは同じサーバーの同じスキーマでのみ実行できるため、機能しません。

3つのオプションがあると思います:

  1. 手動で同期します。他のサーバーのS1のユーザーデータに対して行われたすべてのクエリを実行するスクリプトを呼び出すことにより。ちょっと醜い。

  2. このテーブルのすべてのクエリを1つのサーバーに転送します。 S1にはユーザーテーブルが含まれ、サーバー2上のアプリケーションは、それが何であれ、S2のローカルユーザーテーブルをクエリしませんが、リモートでS1をクエリします。それは良くない。

  3. FEDERATEDエンジンを使用します。 S1にユーザーデータを格納し、S2にFEDERATEDを使用して同じテーブル構造を作成します。つまり、S2は物理的なユーザーデータを保持せず、S1のテーブルへの接続を保持します。 S2で実行されるすべてのアクションはS1で実行されます。 http://en.wikipedia.org/wiki/MySQL_Federated および http://dev.mysql.com/doc/refman/5.0/en/federated-storage-engine。 html これがニーズに合っているかどうかを確認します。

3つのシナリオすべてで、同期間の遅延について説明することは困難です。オプション3は、アプリケーションではなくデータベースのみを調整する必要がある唯一のオプションですが、それが大きな問題かどうかは本当にわかりません。

1
32bitfloat

まず簡単な注意点-IDはおそらく他の回答のルートをたどり、特定のセットアップにフェデレーションを使用します。とはいえ、ユーザーデータを3つ目のデータベースに分割する方が良い解決策になるかどうかについては、少し考えてみる価値があります。

2つのdbから重複を削除しますが、1つの中央認証dbから2つのサイトを機能させるには、かなりの手直しも必要になると思います。

0
James Sinclair