関連付けられているアプリを使用する各ユーザーのGUIDを使用するSQL Server 2000のデータベースで作業しています。どういうわけか、2人のユーザーが同じGUIDになってしまいました。Microsoftがアルゴリズムを使用して、衝突を引き起こす可能性が非常に低いランダムなGUIDを生成することを知っていますが、衝突はまだ可能ですか?
関連付けられているアプリを使用する各ユーザーのGUIDを使用するSQL Server 2000のデータベースで作業しています。どういうわけか、2人のユーザーが同じGUIDになってしまいました。Microsoftがアルゴリズムを使用して、衝突を引き起こす可能性が非常に低いランダムなGUIDを生成することを知っていますが、衝突はまだ可能ですか?
回答:
基本的にはありません。私は誰かがあなたのデータベースをいじくり回したと思います。使用しているバージョンGUIDに応じて、値は一意(バージョン1 GUIDなど)または一意であり、予測不可能(バージョン4 GUIDなど)です。NEWID()関数のSQL Serverの実装では、128ビットの乱数を使用しているように見えるため、衝突が発生することはありません。
衝突の1%の確率で、約2,600,000,000,000,000,000の GUID を生成する必要があります。
基本的にそれらは不可能です!、可能性は天文学的に低いです。
しかし...私が知っている世界で私が唯一の人物で、GUIDコリジョンが一度ありました(そうです!)。
そして私はそれを確信しており、それは間違いではなかったと思います。
Pocket PCで実行されていた小さなアプリケーションでは、操作の最後に、生成されたGUIDを持つコマンドを発行する必要がありました。サーバーで実行された後のコマンドは、実行日とともにサーバーのコマンドテーブルに格納されていました。デバッグしているときに、モジュールコマンドを発行し(新しく生成されたGUIDを添付)、何も起こりませんでした。私はもう一度それを行いました(操作の開始時にGUIDが1回だけ生成されたため、同じGUIDで)、そして何もせず、最終的にコマンドが実行されない理由を見つけようとして、コマンドテーブルを確認しました。現在と同じGUIDが3週間前に挿入されました。これを信じないで、私は2週間のバックアップからデータベースを復元しました。コードを確認したところ、新しいguidは間違いなく新しく生成されました。
編集:これが発生する可能性を大幅に増加させる可能性のあるいくつかの要因があり、アプリケーションはPocketPCエミュレーターで実行されており、エミュレーターには状態の保存機能があります。つまり、状態が復元されるたびにローカル時刻も復元されますまた、GUIDは内部タイマーに基づいています。また、コンパクトフレームワークのGUID生成アルゴリズムは、COMの例よりも完全ではない可能性があります...
それらは理論的には可能ですが、3.4E38の可能な数で、1年に数十兆のGUIDを作成する場合、1つの複製が作成される可能性は0.00000000006です(出典)。
2人のユーザーが同じGUIDで終わった場合、データがコピーまたは共有される原因となっているプログラムにバグがあることに賭けます。
まず、2つのGUIDの衝突の可能性を見てみましょう。他の回答が述べているように、誕生日のパラドックスのために2 ^ 128の1(10 ^ 38)ではありません。つまり、50%の確率で2つのGUIDが衝突する確率は、実際には2 ^ 64の1(10 ^ 19)はるかに小さいです。ただし、これは依然として非常に大きな数であり、そのため、妥当な数のGUIDを使用していると想定して衝突する可能性は低くなります。
また、多くの人も信じているように、GUIDにはタイムスタンプやMACアドレスが含まれていないことにも注意してください。これはv1 GUIDにも当てはまりましたが、現在はv4 GUIDが使用されています。これは単なる疑似乱数であり、時間とマシンに固有ではなくなっているため、衝突の可能性は間違いなく高くなります。
したがって、本質的には答えは「はい」です。衝突が発生する可能性があります。しかし、その可能性はほとんどありません。
編集:2 ^ 64と言うように修正
1 in 10^64 (10^19)
あります1 in 2^64 (10^19)
。また、誕生日のパラドックスが2つの数字にしか当てはまらないのではないかと非常に混乱しています。en.wikipedia.org/wiki/Birthday_paradoxを見たと思います。次の表は、特定の重複確率で必要なGUIDの数を示しています。その表から、10 ^ 18で1の確率は2.6 * 10 ^ 10 GUIDを必要とし、2つのGUIDに近いものは必要ありません。
2つのランダムなGUIDが衝突する可能性(10 ^ 38で〜1)は、破損したTCP / IPパケットを検出しない可能性(10 ^ 10で〜1)よりも低いです。 http://wwwse.inf.tu-dresden.de/data/courses/SE1/SE1-2004-lec12.pdf、11ページ。これは、ディスクドライブ、CDドライブなどにも当てはまります。
GUIDは統計的に一意であり、データベースから読み取ったデータは統計的にのみ正しいです。
この場合、私はOccamのかみそりを良いガイドと見なします。GUIDの衝突が発生する可能性はほとんどありません。それはあなたがバグを持っているか、誰かがあなたのデータをいじっている可能性がはるかに高いです。
WikipediaのGlobally Unique Identifierの記事を参照してください。GUIDを生成するにはいくつかの方法があります。どうやら古い(?)の方法はMacアドレス、非常に短い単位までのタイムスタンプ、および一意のカウンター(同じコンピューターで高速な世代を管理するため)を使用していたため、それらを複製することはほぼ不可能です。しかし、これらのGUIDは、ユーザーの追跡に使用できるため、削除されました...
Microsoftで使用されている新しいアルゴリズムがわかりません(一連のGUIDを予測できるとのことで、もうタイムスタンプを使用していないように見えますか?上記のMicrosoftの記事は別のことを言っています...)。
現在、GUIDは、名前によってグローバルに一意になるように注意深く設計されているため、不可能であるか、非常に確率が非常に低いというリスクがあります。私は他の場所を見るでしょう。
MACアドレスが重複しているイーサネットカードを備えた2台のWin95マシンは、特に建物の電源がオフになり、両方がまったく同時に起動する場合など、厳しく制御された条件下で重複したGUIDSを発行します。
私はこれを「ネットワーキングの人ではないので、完全に一貫性のない文章を後にするかもしれません。」で始めます。
イリノイ州立大学で働いていたとき、デルのデスクトップが2台あり、注文のタイミングが異なっていました。1つ目をネットワークに配置しましたが、2つ目をネットワークに配置しようとすると、異常なエラーが発生し始めました。多くのトラブルシューティングの結果、両方のマシンが同じGUIDを生成していることが判明しました(正確には何なのかわかりませんが、ネットワーク上で両方が使用できなくなりました)。デルは実際に両方のマシンを欠陥品として交換しました。
私は、GUIDが魔法で一意であることが保証されているという気持ちのいい答えが好きな人を知っていますが、実際には、ほとんどのGUIDは121ビットの乱数にすぎません(7ビットがフォーマットに無駄に費やされています)。大きな乱数を快適に使用できない場合は、GUIDを使用しても快適ではありません。
にやにや笑うために、次のスクリプトを試してみてください...(SQL 2005で動作しますが、2000についてはわかりません)
declare @table table
(
column1 uniqueidentifier default (newid()),
column2 int,
column3 datetime default (getdate())
)
declare @counter int
set @counter = 1
while @counter <= 10000
begin
insert into @table (column2) values (@counter)
set @counter = @counter + 1
end
select * from @table
select * from @table t1 join @table t2 on t1.column1 = t2.column1 and t1.column2 != t2.column2
これを繰り返し実行すると(1秒未満かかります)、非常に短い時間ギャップがあっても、最初の選択からかなり広い範囲が生成されます。これまでのところ、2番目の選択では何も生成されていません。
次のような方法でGUIDの衝突を生成する可能性はほとんどありません。 NEWID()
SQL Server関数の(もちろん、他の回答が強調しているように可能ですが)。彼らが指摘していないことの1つは、実際のブラウザーでJavaScriptでGUIDを生成している場合、衝突に遭遇する可能性が非常に高いということです。さまざまなブラウザーでのRNGに問題があるだけでなく、Googleスパイダーがそのような関数の結果をキャッシュしているように見えて、同じGUIDをシステムに繰り返し渡してしまう問題にも遭遇しました。
詳細については、こちらのさまざまな回答をご覧ください。