4

MySQL残念ながら、レプリケーション/クラスターでセットアップできない特定のデータベースの独自のインスタンスを実行しているサーバーがいくつかあります。user各サーバーは、間に外部キー制約がある複数のユーザー関連テーブルにデータを挿入します (例: user_vote)。プロセスは次のようになります。

  1. すべてのサーバーは同じデータで開始します
  2. 各サーバーは、他のサーバーから独立して独自のデータ セットを拡張します。
  3. 定期的に、すべてのサーバーからのデータが手動でマージされ、各サーバーに適用されます (したがって、プロセスはステップ 1 から繰り返されます)。

これが可能になるのは、主キーに加えて、userテーブルに一意のemailフィールドが含まれているためです。これにより、各データベースに既に存在しているユーザーを識別し、主キーと外部キーを変更しながら新しいユーザーをマージして衝突を回避し、正しい情報を維持できます。外部キー制約。それは機能しますが、衝突を避けるために主キーと外部キーを変更する必要があるため、かなりの労力が必要です。したがって、私の質問:

マージを容易にするために、各サーバーに他のサーバーと衝突しない主キーを使用させる方法はありますか?

server_id最初は複合主キー ( , などid)を使用したかったのですDoctrineが、複数の外部キーで構成される主キーをサポートしていないものを使用しているため、外部キーの制約に問題がありました。

aVARCHARを an として使用idし、文字列の一部をプレフィックス (SERVER1-1、SERVER1-2、SERVER2-1、SERVER2-2...) として使用することを考えましたが、DB が遅くなると思います。 IDでいくつかの操作を行う必要があります(たとえば、挿入時に、既存のIDを解析して最高のものを抽出し、インクリメントし、サーバーIDと連結する必要があります...)。

PS: 別のオプションとして、スレーブからの読み取りとマスターへの書き込みを使用してレプリケーションを実装することもできますが、このオプションは、レプリケーション ラグやマスターでの単一障害点などの問題があり、現時点では解決できないため、破棄されました。

4

2 に答える 2

3

各サーバーが自動インクリメントの異なるインクリメントと異なる開始オフセットを使用していることを確認できます。

ステップの auto_increment フィールドの増分を次のように変更します

(auoincrementsを使用していると仮定)

私はこれを 2 つのサーバーでしか使用したことがないため、セットアップには 1 つの ID が偶数で、もう 1 つの ID が奇数でした。

すべてのテーブルが上記の考え方に従っていることを確認している限り、それらが再びマージされたときに衝突することはありません。

4台のサーバーに実装するために

次のオフセットを設定します。

  • サーバー 1 = 1
  • サーバー 2 = 2
  • サーバー 3 = 3
  • サーバー 4 = 4

増分を次のように設定します (追加のサーバー用のスペースを確保するために 10 を使用しました)。

  • サーバー 1 = 10
  • サーバー 2 = 10
  • サーバー 3 = 10
  • サーバー 4 = 10

そして、マージした後、各サーバーにコピーして戻す前に、各テーブルの autoinc 値を更新して、正しいオフセットを再度取得する必要があります。各サーバーが 100 行を作成したと仮定すると、autoincs は次のようになります。

  • サーバー 1 = 1001
  • サーバー 2 = 1002
  • サーバー 3 = 1003
  • サーバー 4 = 1004

これは、サーバーが 4 つあるために注意が必要な場所です。たとえば、特定のテーブルに特定のサーバーから挿入された行がなかったとします。そのため、最後の autoinc ID がサーバー 4 からではなく、サーバー 2 からのものであるいくつかのテーブルになる可能性があります。これにより、特定のテーブルの次の autoinc がどうあるべきかを判断するのが非常に難しくなります。

このため、行が挿入されたときにサーバー番号を記録する列を各テーブルに含めることをお勧めします。

id | field1 | field2 | ... | server

こうすることで、任意のテーブルで以下を選択することで、特定のサーバーの最後の autoinc 値を簡単に見つけることができます。

SELECT MAX(id) FROM `table` WHERE `server`=4 LIMIT 0,1

この値を使用すると、マージされたデータセットを問題のサーバーにロールアウトする前に、各サーバーの各テーブルに必要な次の autoinc 値をリセットできます。

UPDATE information_schema.tables SET Auto_increment = (
  SELECT MAX(id) FROM `table` WHERE `server`=s LIMIT 0,1
)+n WHERE table_name='table' AND table_schema = DATABASE();

はサーバーs番号でn、オフセットに設定されているため、私の例では10.

于 2012-11-24T12:20:03.067 に答える
1

ID をプレフィックスするとうまくいきます。DBが遅いことについては、そこで処理されるトラフィックの大きさに依存します。また、「プレフィックス付き ID」を「プレフィックス」と「ID」の 2 つの列に分割することもでき、これらは任意のタイプにすることができます。リクエストでそれに対処するには何らかのロジックが必要ですが、評価する価値があるかもしれません

于 2012-11-24T12:19:50.753 に答える