我可以将 Unix 时间用于数据库中的复合主键吗?

Can I use Unix Time for composite primary keys in database?

在我的数据库中,我们使用由用户 ID 和当前 date/time 生成的复合主键:

CREATE TABLE SAMPLE (
    Id bigint NOT NULL, -- generated from ticks in UTC timezone
    UserId int NOT NULL,
    Created timestamp without time zone NOT NULL,
    ...
    PRIMARY KEY (UserId, Id)
)

作为 Id 我们使用 DateTime.UtcNow.Ticks.NET Framework.

现在我想用毫秒Unix Time来代替,因为不知道的人会更容易使用.NET Framework

使用Unix Time作为组合主键有什么潜在的问题吗?我听说它不会保存闰秒,但我不确定如果我在数据库中使用它作为我的 ID 是否会导致任何实际问题。

请注意,我不使用生成的 ID 来创建 date/time - 我们始终有一个单独的 Created 字段用于此。我们也不会每秒生成超过一条记录,因此重复不是问题。

我最担心的是,您可能会在同一时间戳中创建多行,从而在第一行和所有后续行之间造成冲突。

Unix 时间通常以整秒为单位,但即使您将精度提高到毫秒,您仍然可能最终对多个记录使用相同的临时缓存值,具体取决于如何读取时间戳的实现细节系统时钟。

即使使用 DateTime.UtcNow.Ticks,在某些情况下,紧密循环中的多个调用 也可能 return 具有相同的值。与 getutcdate 或其他类似 SQL 的命令相同。

如果您需要整数唯一标识符,最好使用自动递增整数,这是大多数数据库的内置功能。

只要它们是唯一的(复合键中每个其他字段每秒不超过一个)Mysql 将允许键的时间戳就可以了。

不过,我很担心你的说法

We also never generate more than one record per second, so duplicates are not a problem.

我听过很多次了。

  • "We'll never have parellel request"
  • "We'll never get this many requests per second, etc..."

警告你一下,这是天大的诱惑,等会儿就有人骂你了。

根据您的评论,您添加了检测和 backoff/retry 冲突(密钥拒绝),如果您水平扩展请留意,因为这仍然是您可能会遇到问题的地方

  • 例如,如果您的服务器有轻微的时间戳,即使使用毫秒时间戳,您也可能会重叠并频繁发生冲突——毫秒并不像您想象的那样精细,尤其是当您横向扩展时(我在负载平衡服务器上发生过这种情况,当我试图根据时间戳和其他一些蹩脚的启发式方法创建我们自己的 UUID 函数。
  • 我建议现在解决它,甚至不要通过使用数据库中的增量列、UUID 或至少其他随机数字段之类的东西来解决它。