跨服务器管理身份验证/主键

8

我正在设计一个新的数据库,需要支持复制功能,但我卡在了选择主键的决定上。

我们目前的数据库使用两个int列作为主键,第一列是自增列,另一个用于描述插入该行的服务器。现在我想避免使用两个列作为主键,而只使用一个列。到目前为止,我有两种方法:

  1. 使用GUID作为我的主键

    这将确保任何数量的服务器上都有唯一的键。我不喜欢这种方法的原因是GUID占用16字节的空间,在跨多个表的外键中使用时会浪费空间。同时在编写查询时使用它更加困难且查询速度较慢。

  2. 使用int或bigint,并手动为每个服务器上的每个表指定种子和递增值。例如,如果有两个服务器,则第一个服务器上的X表将从1开始,第二个服务器上的X表将从2开始,每个表的递增值都为2。因此,第一个服务器上将有(1,3,5,...),第二个服务器上将有(2,4,6,...)。这种设计的好处是编写查询时更容易使用,速度快,外键使用的空间更少。坏处是我们永远不知道将运行多少服务器,因此很难确定递增值。此外,在服务器上管理模式更加困难。

在管理多个服务器时,有什么最佳实践?在这种情况下,是否有最佳方法?


1
但即便有两个“int”字段,仍然只有8个字节(而不是GUID的16个字节)... 此外:两个“int”作为聚集键比GUID更好 - 在SQL Server中使用GUID作为聚集键非常糟糕 - marc_s
另一种选择是使用复合键,其中一列用于服务器,另一列用于服务器特定的int。(GUID是16个字节;这些字节中没有一个是浪费的。你可能能想出一个更小的键,但这并不意味着GUID是浪费的。它只是比其他更窄的键稍微宽一点。在这里,“浪费”只是一个不好的术语,因为它限制了你的思维。) - Mike Sherrill 'Cat Recall'
3个回答

2

您的问题很好,而且经常被问到。

从维护的角度来看,我绝对会选择GUID。它们存在是有原因的。 在某个时候,您可能会遇到复杂的操作,移动和重新复制数据,然后其他选项可能会使它变得比必要的更加复杂。

这里有一个非常好的短篇阅读介绍了各种选项:

http://msdn.microsoft.com/en-us/library/bb726011.aspx

至于复制部分 - 如果正确执行,复制就没有真正的麻烦。


0

我敢建议完全不要复制 :) 它肯定比有趣更痛苦。如果您负担得起,请考虑使用同步框架

玩弄身份识别至少不够灵活。考虑添加移动服务器。身份插入,不同的模式等等。

如果您使用newsequentialid()作为默认值,则GUID将是一个集群键。它稍微大一些(一些位数),但它解决了麻烦 :)

我会选择一个仅与数据库上下文相关的int identity集群键。然后添加一个GUID列,这对于同步上下文很有意义。最后加上一个rowversion列以查看何时可以进行同步。


0

更新:

发现了一种更简单/手动的方法这里。涉及使用NOT FOR REPLICATION和像您在评论中提到的那样交错标识种子值。

原文:

你最好选择类似于第二个选项的东西。为复制发布者和订阅者实例分配标识范围,然后打开自动范围管理。

本文讨论了在复制中管理标识列的选项,启用标识范围管理在此处讨论。

由于您不知道复制池中会有多少服务器,因此您可能需要定期重新配置文章属性。


据我所理解,它的工作原理是为每个服务器指定一些范围,例如1-10000、10001-20000、20001-30000等等... 我认为身份范围可能不是最好的方法。 也许对于我的系统,我可以假设最多有10台服务器,然后从那里开始。因此,我的增量将在每个服务器上增加10,并且起始值将在1-10的范围内。 - Mladen Macanović
我不理解你提议在每个服务器上按10进行,范围从1-10。你能否详细说明为什么身份范围选项不适合你的环境? - Bryan
假设有两个服务器。在第一个服务器上,我们创建一个空数据库,在第二个服务器上,我们也创建一个空数据库。 现在,在第一个数据库中,我们将每个表的标识键设置为从数字1开始。在第二个数据库中,我们将其设置为从数字2开始。 在每个数据库中,标识将增加2。因此,在db1上将是(1,3,5,7,9,...到最大bigint),而在db2上它们将变为(2,4,6,8,...到最大bigint)。 - Mladen Macanović
这种方法的好处是我们只需要在创建数据库时执行一次。坏处是我们不知道未来会有3、4甚至10个服务器。这就是为什么我说我可以假设未来会有10个服务器,这样我们就有一些空间来添加它们(如果需要的话)。 - Mladen Macanović

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