私は、関連付けられているアプリを使用する各ユーザーの GUID を使用する SQL Server 2000 のデータベースに取り組んでいます。どういうわけか、2 人のユーザーが同じ GUID を持っていました。Microsoft がアルゴリズムを使用して、衝突を引き起こす可能性が非常に低いランダムな GUID を生成していることは知っていますが、それでも衝突は可能ですか?
19 に答える
基本的に、いいえ。誰かがあなたのデータベースをいじったと思います。使用しているバージョン GUID に応じて、値は一意 (バージョン 1 GUID など) か、一意で予測不可能 (バージョン 4 GUID など) です。SQL Server の NEWID() 関数の実装では、128 ビットの乱数が使用されているように見えるため、衝突は発生しません。
衝突の可能性が 1% の場合、約2,600,000,000,000,000,000 のGUIDを生成する必要があります。
基本的にできません!、可能性は天文学的に低いです。
しかし... 私が知っている世界で、一度 GUID の衝突があったのは私だけです(そうです!)。
そして、それは間違いではなかったと確信しています。
Pocket PC で実行されていた小さなアプリケーションで、操作の最後に生成された GUID を持つコマンドを発行する必要があるのはどうしてですか。サーバー上で実行された後のコマンドは、実行日とともにサーバー上のコマンドテーブルに格納されました。ある日、デバッグ中にモジュール コマンド (新しく生成された GUID を添付) を発行しましたが、何も起こりませんでした。もう一度やり直しました (GUID は操作の開始時に 1 回しか生成されなかったため、同じ GUID を使用して)、もう一度何もせず、最終的にコマンドが実行されない理由を突き止めようとして、コマンド テーブルを確認しました。現在のものと同じ GUID が 3 週間前に挿入されました。これを信じずに、2 週間分のバックアップからデータベースを復元したところ、GUID がそこにありました。コードを確認したところ、間違いなく新しい GUID が新たに生成されました。
編集:これが発生する可能性を大幅に高める要因がいくつかあります。アプリケーションはPocketPCエミュレーターで実行されていました。エミュレーターには状態保存機能があります。つまり、状態が復元されるたびに、ローカル時間も復元されます。 GUIDは内部タイマーに基づいています....また、コンパクトフレームワークのGUID生成アルゴリズムは、たとえばCOMのものよりも完全ではない可能性があります...
理論的には可能ですが、可能な数が 3.4E38 の場合、1 年間に数十兆の GUID を作成すると、1 つの重複が発生する可能性は 0.00000000006 (ソース) になります。
2 人のユーザーが同じ GUID を持つことになった場合、プログラムにバグがあり、データがコピーまたは共有されている可能性があります。
まず、2 つの GUID が衝突する可能性を見てみましょう。他の回答が述べているように、誕生日のパラドックスのため、2^128 (10^38) に 1 ではありません。つまり、2 つの GUID が衝突する確率が 50% の場合、確率は実際には 2^64 に 1 (10^ 19) はかなり小さいです。ただし、これは依然として非常に大きな数であるため、適切な数の GUID を使用していると仮定すると、衝突の可能性は低くなります。
多くの人が信じているように、GUID にはタイムスタンプや MAC アドレスが含まれていないことにも注意してください。これは v1 GUID に当てはまりましたが、現在は v4 GUID が使用されています。これは単なる疑似乱数であり、時間とマシンに固有のものではないため、衝突の可能性が間違いなく高くなります。
したがって、本質的に答えはイエスです。衝突は可能です。しかし、その可能性は非常に低いです。
編集:2 ^ 64と言うように修正
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 は統計的に一意であり、データベースから読み取ったデータは統計的に正しいだけです。
この場合、オッカムの剃刀は良いガイドだと思います。GUIDが衝突する可能性は非常に低いです。バグがあるか、誰かがデータをいじっている可能性がはるかに高くなります。
Wikipedia のGlobally Unique Identifierの記事を参照してください。GUID を生成するには、いくつかの方法があります。どうやら古い (?) 方法では、Mac アドレス、非常に短い単位までのタイムスタンプ、および一意のカウンター (同じコンピューター上で高速な世代を管理するため) を使用していたため、それらを複製することはほぼ不可能です。しかし、これらの GUID は、ユーザーの追跡に使用される可能性があるため削除されました...
Microsoft が使用する新しいアルゴリズムについてはよくわかりません (この記事では、一連の GUID を予測できると書かれていますが、タイムスタンプを使用していないように見えますか? 上記のリンクにある Microsoft の記事では、別のことが述べられています...)。
現在、GUID は、名前がグローバルに一意になるように慎重に設計されているため、不可能であるか、非常に低い可能性があるというリスクがあります。私は他の場所を見ます。
重複した MAC アドレスを持つイーサネット カードを搭載した 2 台の Win95 マシンは、厳重に管理された条件下で重複した GUID を発行します。たとえば、建物の電源が切れて、両方がまったく同時に起動した場合などです。
GUID は魔法のようなものであり、一意であることが保証されているという気持ちの良い答えが好きな人がいることは知っていますが、実際には、ほとんどの GUID は 121 ビットの乱数にすぎません (ビットの 7 つはフォーマットに無駄になっています)。大きな乱数を使用することに慣れていない場合は、GUID を使用することに抵抗を感じるべきではありません。
「私はネットワーキングの人ではないので、以下の文章は完全に支離滅裂な文章になるかもしれません.」と前置きします。
私がイリノイ州立大学で働いていたとき、異なる時期に注文した 2 台の Dell デスクトップがありました。最初のものをネットワークに配置しましたが、2 番目のものをネットワークに配置しようとすると、おかしなエラーが発生し始めました。トラブルシューティングを重ねた結果、両方のマシンが同じ GUID を生成していることが判明しました (正確な理由はわかりませんが、両方ともネットワーク上で使用できなくなりました)。デルは実際に両方のマシンを欠陥品として交換しました。
GUID の生成に使用されるコードにバグがある可能性はありますか? はい、もちろん可能です。しかし、答えはコンパイラのバグの場合と同じです。あなた自身のコードは桁違いにバグがある可能性が高いので、最初にそこを調べてください。
もちろん可能です....可能性はありますか?可能性は低いですが、可能です。
同じマシンがすべての 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の衝突ではなくバグである可能性が高いため、個人的には他の場所を探します...
もちろん、短くするために GUID からビットを切り取らないようにします。
確かにそれは可能であり、おそらく可能性さえあります。各 GUID が可能な数値空間のランダムな部分にあるわけではありません。2 つのスレッドが 1 つのスレッドを同時に生成しようとした場合、セマフォで囲まれたある種の集中型 GUID 関数がなければ、それらは同じ値になる可能性があります。