【问题标题】:GUID in databases other than SQL ServerSQL Server 以外的数据库中的 GUID
【发布时间】:2011-03-29 07:55:52
【问题描述】:

问题:我目前正在为我的一个程序规划数据库。

我打算将 ASP.NET MVC 用于用户后端,数据库位于 Linux 和/或 Windows 上。

现在,即使我只针对 Windows,我也必须考虑到不同的客户使用不同的数据库系统。现在,我想我使用 nHibernate,然后我可以将所有内容放入代码中,它适用于所有市长数据库,例如 Oracle/Sybase/MS/PostGre/MySQL/Firebird。

我现在的探针是 GUID。 SQL Server 使用 GUID,而其余的使用整数自动增量作为主键。虽然理论上自动增量更好,但它会产生保持多个数据库同步的问题,或者手动更改事物的问题,这需要 CSV 导入/导出...

现在,由于 autoid 在实践中存在的固有问题,我更喜欢 GUID 系统。由于 guid 是一个 36 个字符的字符串,我可以使用 varchar(36) 作为主键,但使用 varchar 作为 GUID,可能不是一个理想的解决方案...

您将如何解决这个问题/您使用什么作为主键? 或者你如何避免自动增量问题,比如插入一个 csv 文件而不更改 autoid...

【问题讨论】:

  • 只是不要将您的 GUID 用作 SQL Server 中的主键/集群键 - 在此处查看原因:sqlskills.com/BLOGS/KIMBERLY/post/…
  • 但是...,如果 auto-id + GUID 不是一个好主意,那该怎么办?
  • 我想你会发现 GUID 比自动递增整数 ID(SQL Server 也有 BTW)会造成更大的混乱。
  • GUID 如何造成混乱?我知道使用 autoinc 导入以前导出的 CSV 文件。整数会造成很大的混乱,因为它会更改在其他地方引用的所有主键......但是 GUID,你怎么能把它们弄得一团糟?我想知道如何...

标签: sql nhibernate database-design orm auto-increment


【解决方案1】:

我在使用 Guids 时从来没有遇到过任何问题。我们在具有许多记录(数百万)的系统中使用 Guid.Comb,并且由于 Guid 本身而没有遇到任何问题。对我来说,卖点是我可以在将某些内容保存到数据库之前生成 Id。即使在客户端。这在 CQRS 场景中非常有用。 我认为您还应该考虑的唯一一件事是人类可读性。在让我们说主/细节场景中查看数据库和匹配记录是很困难的。

还有一个关于 Firebird 的注释...... Uuid 被写成一个八位字节。而且我用来管理数据库的大多数客户端都无法以体面的格式表示它们。所以它通常只显示为几个字符(可能只是将字节数组解码为字符串)。我不知道其他供应商。例如 SQLServer Management Studio 就可以很好地展示它们。

【讨论】:

  • 由于他使用的是NHibernate,所以他的bigint/int ids也可以在去db之前使用hilo算法生成。
  • 确实如此。不过,还有另一个问题。如果您将实体封装在其他实体的列表中,那么这些子实体会在 NHibernate 持久化它们时分配它们的 ID。使用 Guid,所有实体都在对象实例化时分配了 ID。或者换句话说,您只有在调用 MakePersistent 或等效项时才会获得 ID。
【解决方案2】:

Oracle 和 PostgreSQL 也支持 GUID,因此没有必要在那里使用序列(当然 Diego 是对的:如果您使用自己的算法来创建 GUID,您始终可以使用带有您自己生成的 GUID 的 varchar 列来存储)

请注意,它拼写为 PostgreSQL,而不是 PostGre

【讨论】:

    【解决方案3】:

    使用 guid.comb 生成器密钥的 Guid 密钥可用于任何数据库,即使它没有 Guid 作为本机类型。

    【讨论】:

      【解决方案4】:

      您还可以考虑生成一个主键,它是自动增量(即设置序列)和生成它的机器的唯一标识符的组合,可能使用 MAC 地址。

      请参阅this 进行讨论。

      这样您就有了一个本地唯一的(由于序列)ID,它也是全球唯一的(由于 MAC 地址部分)。

      我知道,我知道,you can spoof a MAC address 但您可以自行决定这是否真的对您的域构成风险。此外,当你测试你的代码时,欺骗它的能力可能会很方便。


      请更好地解释当新客户数据库诞生时会发生什么。它会在服务器上注册吗?如果是,您可以在服务器上分配一个 DB-id,并使用它来代替 MAC 地址,只需为每个新 DB 分配一个编号并与序列一起使用。

      基本上,如果您想要一个“唯一的数据库实例 ID”来避免“表 ID”冲突,您只有两个选择:

      1) 每当添加新数据库时,服务器都会分配数据库 ID

      2) 客户端自动生成一个唯一 ID,这通常需要使用 MAC 地址,“原始”或以某种方式处理。

      老实说,鉴于您当前对问题的描述,我看不到替代方案。

      【讨论】:

      • MAC 地址 GUID 部分已在 .NET 中删除(我认为在 SP 1 中)。这不是一个好主意,因为如果用户得到一个 GUID(发送到他的机器),他可以重建服务器 MAC 地址,这为各种滥用打开了大门。当然,将 GUID 与自动增量相结合将是一个非常愚蠢的想法,因为它结合了 GUID 和自动增量这两个系统的问题......
      • 我对您的方案了解得不够多,无法提供具体建议 - 这取决于应用程序的使用方式:如果您确定始终有一个不同的服务器,您可以将其 MAC 地址部分替换为一个任意数字(例如零)。您还可以在 MAC 地址上使用单向编码功能。也许如果您更详细地解释服务器/节点之间的关系,我可以更具体。如果一个新节点注册到服务器,您可以删除 mac 地址并为每个卫星数据库分配一种“站点 ID”。
      • 我试图更好地解释这一点,检查修改后的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多