SQL Server唯一GUID

5
我了解在SQL Server中GUID通常是唯一的,而且发生冲突的可能性很小,但同时也必须考虑到有人会赢得彩票,因此我觉得为这种情况做好准备是有意义��。
哪种方法更快/更好的实践呢?
使用一种技术,通过插入一行并检查错误(@@ERROR <> 0)来直接分配一个新的GUID,并重复该过程,直到不再出现错误[理论上最坏的情况只会出现一次...];
还是使用类似以下的方法:
DECLARE @MyGUID uniqueidentifier
SELECT @MyGUID = NewID()
if exists(select * from tablename where UserID=@MyGUID)

我会循环遍历,直到找到一个未被使用的。

我喜欢第二种方法,因为我可以在稍后的存储过程中使用GUID,所以我目前倾向于使用这种方法。


6
如果你在连续三个周末中赢得彩票,就要开始担心应用程序中潜在的GUID冲突了...虽然这种可能性是非常非常小的--你必须每秒创建数百万个GUID长达数个世纪,才有可能出现重复。难道你没有更紧迫的事情需要担心吗?!?!? - marc_s
5个回答

7
如果您的计算机至少有一个网络适配器,则您的GUID将是唯一的。如果没有,则在理论上存在与另一台计算机生成的guid冲突的可能性,但这永远不会发生在您身上。编写代码以防止重复的guid是完全浪费时间。
话虽如此,在关系型数据库中强制执行任何东西的唯一性只有一种方法:在数据上创建唯一约束。请参考unique constraint
ALTER TABLE tablename ADD CONSTRAINT uniqueUSerID UNIQUE UserID;

3
据我所知,Windows API现在不再使用MAC地址创建GUID(现在基本上只是随机的),而SQL Server使用顺序算法来处理索引聚集问题。 - MusiGenesis
是的,Win2000+有完全(伪)随机的GUID。Remus所说的关于MAC地址的内容只适用于NT4,但他所说的其他一切都是正确的 :) - Jan 'splite' K.

5
在您的计算机上发生碰撞的可能性比您赢得彩票要小得多
使用 NEWID(),不必担心极不可能的事件。
如果您将列声明为唯一,则无论如何都不会持续存在。

1
@MusiGenesis - 我认为“今年吃三明治的概率”高度依赖于地理和文化因素,有些组合可能比“GUID冲突的可能性”更低 ;) - Oded
1
一个大麦克堡汉堡算不算“三明治”?这些家伙现在相当普遍。 :) - MusiGenesis
@MusiGenesis - 不知道。但是:http://en.wikipedia.org/wiki/List_of_countries_with_McDonalds_franchises#Former_locations - Oded
3
@Musigenesis:这几乎让我想起了《银河系漫游指南》中的“不可能驱动器” :-) - marc_s
1
@Musigenesis - 不可能驱动器对@marc_s的影响 - Oded
显示剩余2条评论

4

为了真正回答这个问题,而不是讨论问题/看法是否有益。

第一个实现方式是你想用的,因为:

  • 在处理每条记录之前运行检查是否存在会导致更多的资源被分配到极不可能发生的事情上。(数据库也会确保列上的约束性,所以如果发生冲突,数据不会被提交)
  • 如果第一个实现遇到错误,你可以花点额外的时间来处理返回的ERROR。

你可以将两者结合起来,声明新的唯一标识符插入表中(如果成功,则继续使用它,否则重试,并继续使用它)。

通常情况下,你应该首先为最有可能的情况编写程序,然后再处理异常情况。


3

发生碰撞的概率非常低——远远小于中彩票的概率——更有可能是宇宙射线打击机器内存,导致程序以其他任意方式失败。更有可能是您对此情况的错误处理(现在或将来)包含了会导致失败的错误。研究人员试图使用大量计算能力故意寻找碰撞,但到目前为止还没有成功找到一个。我认为在您处理可能出现的更广泛的硬件和软件错误之前,不值得花费时间和精力来处理这种错误情况。我知道这个想法很反直觉,但请相信我。


这并不违反直觉,我真的意识到碰撞的可能性非常低。我也将其作为一种思考方式来探索哪种方法更快捕捉罕见错误并在发生时处理它,或者在给定情况下在每次插入之前进行查询以查看是否存在。有时候,我发现捕捉罕见错误比一直检查它们要快。 - Jordan

1
通常情况下,我只在处理需要离线添加新记录的分布式数据库时使用GUID主键。如果这不是您的情况,最好使用自增的int作为主键。

我知道这不是解决方案本身,而是通过混淆来实现安全。我正在通过ajax传递一些userid信息,因此用户可以看到他们的ID,我希望其他人无法猜测到其他用户的ID。我已经采取了措施防止他们能够使用它们,但我想使用GUID作为额外的措施。 - Jordan
1
@Jordan:你的系统应始终要求通过用户ID和密码进行身份验证。能够猜到其他用户的ID不应使他们能够访问任何内容。此外,最好在客户端生成GUID,而不是在SQL Server中生成,因为SQL Server的GUID有意是顺序的(虽然我不知道这个顺序是否真的可猜测)。 - MusiGenesis
1
SQL Server中由newid()生成的GUID不是顺序的 - 由newsequentialid()生成的GUID在某种程度上是顺序的... - marc_s
1
@marc_s:你指望我说的话准确吗?唉。 - MusiGenesis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接