EDITED:主キーの
あなたのオリジナルのデザインを使用AUTO INCREMENT
列。この問題は、最終的にマージされる別々のデータベースに同時にデータが入ったときに表示されるようになると、重複するキーが作成されることになります。
各代替データベースでシーケンスを使用することもできます。残念ながら、シーケンスはmysql(Oracleなどの他の多くのデータベース、db2はそれらを持っています - このタイプの分散データベースの挿入は衝突なしで可能です)ではネイティブに利用できません。 AUTO INCREMENT
列では、必要なレプリケーションの種類が許可されません。
これで2つのオプションが残っています。
1)(最初の回答ごとに)location_idを設定する主キーの余分な部分を追加します。
2)AUTO INCREMENT
列を使用するのではなく、独自のシーケンスを使用して手動でIDを生成します。
それは、シーケンス内の次の値を取得するときに自分自身をコミットするストアドプロシージャ/ファンクションとしてシーケンスを実装するためにおそらく最高だ - これが使用されていない値になってしまうことがあります。これは問題ありません。挿入物全体がコミットされるまでシーケンス番号をコミットするのを待つ場合は、競合よりも優れています。
主なものは、あなたが最初のインサートをやっているとき、あなたはストアドプロシージャからのシーケンス番号を使用することです。データを2番目のdbに効率的に複製すると、元のdbの行に生成されたシーケンス番号が使用されます。そして、シーケンスは、衝突を防ぐために、異なる開始点を持つそれぞれの別々のdbに維持されるだろう。
例えば、各データベースには、次の2個のピースをしたいと思う:
1)各名前のシーケンスの次の使用可能なシーケンス番号を保持するテーブル。 (シーケンスから抽出された主キーを取得する各テーブルはエントリを取得します)。 2)次のシーケンス番号を持つテーブルにアクセスして更新する関数。
サンプルの実装は次のようになります。
シーケンステーブル:
CREATE TABLE sequences (
name varchar(30) NOT NULL,
value int(10) unsigned,
PRIMARY KEY (name)
) ENGINE=InnoDB
シーケンス機能(S):
delimiter //
create function get_next_value(p_name varchar(30)) returns int
deterministic
sql security invoker
begin
declare current_val integer;
UPDATE sequences
SET value = (@current_val:=value) + 1
WHERE name = p_name;
return @current_val;
end //
delimiter ;
主な問題は、格納された機能が単一である必要があるということですそれが完了してすぐにコミットするようにします(そうでなければ、注文が入ったときにトランザクションが互いに後ろに積み重なるようにロックします)。y非常に高いスループットを持っていませんが、これは問題ではありません。
私はこの関数を書いていない - 私は自由にここからそれをコピーしている:私はより多くの詳細については、にあなたを参照することになりhttp://www.bigdbahead.com/?p=185。 (そして、そのユーザーが私をここで見つけたなら、私は彼に答えを書いてもらい、ここにも適切なクレジットを与えることができます)。
ここで、データベースごとに、衝突を避けるために値を別の番号で初期化します。だから、orders
テーブルのために、場所Aで、あなたがこれを初期化したい:
insert into sequences ('orders', 1);
と位置Bで、あなたがこれを初期化したい:両方のデータベースで
insert into sequences ('orders', 1000000);
そして、 orders
への挿入に、あなたがしたい:
insert into orders (order_id, . . .)
select mysql.get_next_value('user_id'), . . . <hardcoded-values>
-
I Hこのソリューションを道路でテストしてはいけません - シーケンスに関する私の答えに示唆していることの概要としてそれを取ってください。上記のブログエントリのリンクをフォローアップする必要があります。具体的には、トランザクション制御下でのこの作業の仕組み、コメント(コメントから関数の形式を取ったもので、元の関数ではありません)もちろん、負荷をかけてテストしてください。
私は衝突に遭遇することはないと確信していますが、少なくとも光の2年前ではありません。しかし、異なる自動インクリメントのルートを割り当てることは私の問題を解決するつもりはありません。 例:structure:Stock(s_id、s_name)注文(o_id、s_id、金額) ワークスペースAは新しいアイテムs1を挿入し、自動インクリメントs1.s_id = 1を割り当てられます。 s_id = 1、これら2つの問合せを作業領域2に送信すると、それは在庫s1を挿入し、自動インクリメントs1.s_id = 100000が割り当てられ、2番目の問合せ「insert into Orders(s_id)values(1)」を実行します。 。私は論理的な解決策がないと思う。 – Haz
私の謝罪 - 改訂版の回答を見てください。私はmysqlの用語ではなく、db2の言葉(私の現在のクライアント)を考えています。そして、一般的に、はい、この問題に対する論理的な解決策があります.Wi-Fiや普及しているインターネット接続の前の日には、dbを配布し、後でデータをマージする必要があったのです。したがって、マージ時の衝突を避けるためのスキームがたくさんあります。 –
はい、私は興味があります。私は少し失われた小さな例に感謝します。そして、私が下に出てきたことについてのあなたの考えを感謝します。 – Haz