3

現在使用しているソフトウェアの 1 つがこの特定のデータベース エンジンしかサポートしていないため、PostgreSQL データベースを使用しています。次に、アプリからのデータをより有用な形式に要約および分割するクエリがあります。

私の MySQL データベースには、上記のクエリの出力と同じスキーマを含むテーブルがあります。

私が開発したいのはcron、PostgreSQL データベースに対してクエリを実行し、結果を MySQL データベースに挿入する 1 時間ごとのジョブです。1 時間の間に、転送が必要な 10,000 を超える新しい行が表示されることはないと思います (これはストレッチです)。

両方のデータベースは、互いに離れた大陸にある別々の物理サーバー上にあります。MySQL インスタンスは Amazon RDS で実行されるため、マシン自体をあまり制御できません。PostgreSQL インスタンスは、サーバーの 1 つの VM で実行されるため、完全に制御できます。

残念ながら、複製が必要なのは、PostgreSQL データベースが情報の収集者としてのみ機能するのに対し、MySQL データベースにはデータを必要とするアプリケーションが実行されているためです。簡単にするために、PostgreSQL からの移動/マージと削除を 1 時間ごとに実行して、クリーンな状態を維持したいと考えています。

明確にするために-私はネットワーク/システム管理者であり、DBAではありません。ある形式を別の形式に変換する際に必要な複雑さのすべてを本当に理解しているわけではありません。私が知っているのは、転送されるデータが 1x VARCHAR、 1x DATETIME、および 6xBIGINT列で構成されていることです。

アプローチについて私が持っている最も近い推測は、スクリプト言語を使用してクエリを作成し、結果を内部データ構造に変換してから、再び MySQL に分割することです。

その際、スクリプトを作成する際に注意すべき特定の良い慣行や悪い慣行はありますか? または-この種の変換を行うのに役立つ可能性のある、私が見るべきドキュメントはありますか? 非常に管理しやすく、十分に文書化されているように見えるスケジューリング ジョブをたくさん見つけましたが、このスクリプトの進行中の性質 (毎時実行) はあまり一般的ではなく、文書化もされていないようです。

どんな提案にもオープンです。

4

2 に答える 2

3

両端で同じデータベース システムを使用し、レプリケーションを使用する

リモート エンドも PostgreSQL である場合、ホット スタンバイでストリーミング レプリケーションを使用して、リモート エンドをローカル エンドと透過的かつ自動的に同期させることができます。

ローカル エンドとリモート エンドの両方が MySQL である場合、binlog レプリケーションなどの MySQL のさまざまなレプリケーション機能を使用して、同様のことを行うことができます。

外部スクリプトを使用して同期する

外部スクリプトを使用しても問題はありません。実際、DBI-Link など (以下を参照) を使用している場合でも、 PgAgentpsqlを使用しない限り、おそらく cron ジョブから外部スクリプト (または ) を使用してレプリケーションを開始する必要があります。

トリガー プロシージャによって維持されるキュー テーブルに行を蓄積するか、新しい行のみを常に確実に選択するクエリを記述できることを確認してください。次に、ターゲット データベースとINSERT新しい行に接続します。

コピーする行が大きすぎてメモリに快適に収まらない場合は、カーソルを使用してFETCHで行を読み取ることができます。これは、コピーする行が大きすぎてメモリに快適に収まらない場合に役立ちます。

私はこの順序で作業を行います:

  • PostgreSQL に接続する
  • MySQL に接続する
  • PostgreSQL トランザクションを開始する
  • MySQL トランザクションを開始します。MySQL が MyISAM を使用している場合は、今すぐ修正してください。
  • おそらくカーソルを介して、またはDELETE FROM queue_table RETURNING *
  • それらをMySQLに挿入します
  • DELETEまだ行っていない場合は、PostgreSQL のキュー テーブルから行を取得します。
  • COMMITMySQL トランザクション。
  • MySQLCOMMITが成功した場合COMMIT、PostgreSQL トランザクション。失敗した場合はROLLBACK、PostgreSQL トランザクションを再試行してください。

PostgreSQLCOMMITはローカル データベースであるため、失敗する可能性は非常に低いですが、完全な信頼性が必要な場合は、PostgreSQL 側で2 フェーズ コミットを使用できます。

  • PREPARE TRANSACTIONPostgreSQLで
  • COMMITMySQLで
  • 次に、MySQL コミットの結果に応じて、COMMIT PREPAREDまたはPostgreSQL で。ROLLBACK PREPARED

これはニーズに対して複雑すぎる可能性がありますが、変更が両方のデータベースで発生するか、どちらのデータベースでも発生しないかを完全に確認する唯一の方法です。

ところで、真剣に、MySQL がMyISAMテーブル ストレージを使用している場合は、おそらくそれを修正する必要があります。クラッシュ時にデータが失われる可能性があり、トランザクションで更新することはできません。InnoDBに変換します。

PostgreSQL で DBI-Link を使用する

多分それは、私が PostgreSQL に慣れているからかもしれませんが、DBI リンク経由PL/Perluで仕事をする PostgreSQL 関数を使ってこれを行うでしょう。

レプリケーションが必要な場合は、DBI-Link を使用して MySQL データベースに接続し、キュー テーブルにデータを挿入するプロシージャを実行しPL/PgSQLます。PL/Perl

DBI-Link には多くの例が存在するため、ここでは繰り返しません。これは一般的な使用例です。

トリガーを使用して変更をキューに入れ、DBI リンクを使用して同期します

新しい行のみをコピーする必要があり、テーブルが追加専用である場合は、新しく編集されたすべての行をメイン テーブルと同じ定義を持つ別のキュー テーブルに追加するトリガー プロシージャを作成できます。INSERT同期する場合は、同期手順を 1 回のトランザクションLOCK TABLE the_queue_table IN EXCLUSIVE MODE;で実行し、データをコピーして、DELETE FROM the_queue_table;. INSERTこれにより、 -only テーブルでのみ機能しますが、行が失われないことが保証されます。UPDATEターゲット テーブルでの処理DELETEは可能ですが、はるかに複雑です。

外部データ ラッパーを使用して MySQL を PostgreSQL に追加する

あるいは、PostgreSQL 9.1 以降では、MySQL Foreign Data WrapperODBC FDW、またはJDBC FDWを使用して、PostgreSQL がリモートの MySQL テーブルをローカル テーブルであるかのように認識できるようにすることを検討します。次に、書き込み可能な CTEを使用してデータをコピーできます。

WITH moved_rows AS (
    DELETE FROM queue_table RETURNING *
)
INSERT INTO mysql_table
SELECT * FROM moved_rows;
于 2012-09-17T08:42:22.597 に答える
0

つまり、2つのシナリオがあります。

1)宛先にソースから独自の構造にデータをプルさせる

2)ソースにデータをその構造から宛先にプッシュさせる

2つ目を試して、postgresqlトリガーまたは特別な「仮想」テーブル、あるいはpl / pgsql関数を作成する方法を見つけてください。そうすれば、外部スクリプトの代わりに、次の方法でプロシージャを実行できます。 cronから、または場合によってはpostgres内からクエリを実行すると、操作スケジューリングの可能性がいくつかあります。postgresの方がはるかに柔軟性があり、データを特別なDIYの方法で操作できるため、2番目のシナリオを選択します。

外部スクリプトはおそらく適切な解決策ではありません。たとえば、バイナリデータを特別な注意を払って処理するか、日付と時刻をDATEからVARCHARに変換してからもう一度DATEに変換する必要があるためです。外部スクリプト内では、さまざまなテキストに保存されたデータはおそらく単なる文字列であり、引用符で囲む必要があります。

于 2012-09-15T13:29:17.073 に答える