2012-03-08 5 views
11

私はリレーショナルデータがMySQLに自然に格納されている場所に設計されたアプリケーションを用意しています。私は常に進化するスキーマを持ち、リレーショナルデータを持たない他のデータを持っているので、私はこのデータを格納する自然な方法がMongoDBにドキュメントとして存在すると考えました。ここでの私の問題は、私の文書がMySQLのプライマリIDを参照していることです。これまでのところ、これは問題なく動作しています。私の懸案事項は、運用トラフィックが入ってバックアップを開始するときに、ドキュメントが変更されたときに矛盾が発生する可能性があり、MySQLデータベース内の正しいIDを指していない可能性があるということです。それをある程度保証する唯一の方法は、アプリケーションをシャットダウンしてバックアップを取ることです。これはあまり意味がありません。バックアップ中に2つの別々のデータストア間で整合性を維持する(MySQLとMongoDB)

同様の戦略を展開する他の人がいなければなりません。特にバックアップ中に、2つのデータストア間のデータ保全性を保証する最良の方法は何ですか?

+2

私はモンゴーで経験が豊富ではなく、これを試して成功した人から聞きたいですがそのようなMongoDBのデータに対して厳密なリレーショナル・インテグリティを保持しようとしています。スケールの完全性を犠牲にすることの貿易を行うために特別に設計されました:/ –

+0

あなたは何をやったのですか? – Aerik

答えて

2

私はこれを行う簡単な方法はないと思います。 Mongoはロールバックサポートと複雑なトランザクションを持たないので、そのような完全性を維持するのは非常に難しいです。これにアプローチする1つの方法は、2つの元帳とみなし、mysql元帳のすべての更新を記録し、それをmongo ledgerで再生して整合性を維持することです。もう1つの解決策は、アプリケーションレベルでこれを行い、書き込みを停止することです。

4

MySQLの視点

すべてのMySQLのデータはInnoDBのを使用する必要があります。

MYSQLDUMP_OPTIONS="--single-transaction --routines --triggers" 
mysqldump -u... -p... ${MYSQLDUMP_OPTIONS} --all-databases > MySQLData.sql 

これは、単一のトランザクションとしてすべてのMySQLのデータのクリーンポイントインタイムスナップショットを作成します。次のようにあなたは、MySQLのデータのスナップショットを作ることができます。

たとえば、この午前0時にこのmysqldumpを起動すると、mysqldump出力のすべてのデータは深夜からのものになります。すべてのデータがInnoDBストレージエンジンを使用していれば、データをMySQLに追加することができます.MongoDBは、バックアップ中であっても、真夜中以降にMySQLに追加された新しいデータを参照できます。

MyISAMテーブルがある場合は、それらをInnoDBに変換する必要があります。追いかけてみましょう。ここでは、InnoDBテーブルにすべてのMyISAMテーブルを変換するスクリプトを作る方法です。

MYISAM_TO_INNODB_CONVERSION_SCRIPT=/root/ConvertMyISAMToInnoDB.sql 
echo "SET SQL_LOG_BIN = 0;" > ${MYISAM_TO_INNODB_CONVERSION_SCRIPT} 
mysql -u... -p... -AN -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" >> ${MYISAM_TO_INNODB_CONVERSION_SCRIPT} 

あなたはすべてのユーザー定義MyISAMテーブルを変換する準備ができているときだけ、このスクリプトを実行します。いずれのシステム関連のMyISAMテーブルも無視され、とにかく触れてはいけません。

MongoDBの視点

私はほとんど知らないために、私はMongoDBのために話すことはできません。しかし、MongoDB側では、MongoDBデータ用のReplica Setをセットアップすると、レプリカに対してmongodumpを使用できます。 mongodumpは特定の時点ではないので、レプリカを切断して(変更をやり直さないように)、レプリカ上でmongodumpを実行する必要があります。レプリカをマスタに再確立します。 Mongodumpを切断されたレプリカセットに対して使用できるかどうかは、開発者または10genから確認してください。

共通の目標

ポイント・イン・タイムが本当に問題になる場合は、すべてのOSのクロックが同じ同期時刻とタイムゾーンを持っていることを確認しますしてください。このような同期を実行する必要がある場合は、mysqldとmongodを再起動する必要があります。すると、mysqldumpとmongodumpのcrontabジョブが同時に終了します。個人的には、MongoDBに投稿されたいと思っているmysqlのIDが計上されることを保証するために、mongodumpを約30秒遅らせるでしょう。

同じサーバー上でmysqldとmongodを実行している場合、MongoDBレプリケーションは必要ありません。 00:00:00(真夜中)にmysqldumpを起動し、00:30:00(深夜30秒後)にmongodumpを起動するだけです。

0

実際には、何らかの外部の確認や執行がなければ、それを行う方法はありません。

本当に完全な整合性を確保する必要がある場合は、mysqlデータ(すべてのレコード)とmongoレコードの両方にタイムスタンプを使用し、ツールを使用してタイムスタンプでフィルタリングされた各データをバックアップしますそれぞれがスケジュールされたバックアップの前に右の既存のレコードのみを選択するためにどのようにあなたが実際にそれぞれを使用しているに応じて、

(クエリとMongoDBのコレクションをダンプするWHERE句でmysqldumpを使用する方法についてhttp://www.electrictoolbox.com/mysqldump-selectively-dump-data/http://www.mongodb.org/display/DOCS/Import+Export+Tools#ImportExportTools-mongodumpを参照してください)たとえば、あなたがMongoDBに書き込むだけで、更新や削除をしない場合は、あなたのMySQLデータベースをバックアップしてからMongoDBをバックアップするのが合理的でしょう。今持っているかもしれない後でそれがバックアップされるためにいくつかの余分なレコードが残っている)、MySQLの何にも対応していないMongoDBレコードをパージします。私が言ったように、それはあなたがそれらをどのように使用しているかに依存します。

ただし、タイムスタンプの余分なオーバーヘッドがあっても、タイムスタンプは問題なく動作します。

+1

もちろん、あなたのスキーマにある自動インクリメントIDを代わりに使うこともできます。 mysqldump -uuser -p mydb --tables my_documents_table --where = "id <= 2000122" | gzip> my_documents_table_YYYYMMDDHHMMSS.sql.gz mysqldump -uuser -p mydb --ignore-table = mydb.my_documents_table | gzip> mydb_YYYYMMDDHHMMSS.sql.gz 次に、mongodumpユーティリティを使用して、選択したドキュメントID範囲を含むレコードのみを選択できます。 – wisefish

関連する問題