我可以在数据库中使用Unix Time作为复合主键吗?

时间:2016-09-20 19:09:19

标签: database timezone unix-timestamp

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

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来获取创建日期/时间 - 我们总是有一个单独的Created字段。我们也绝不会每秒生成多个记录,所以重复不是问题。

2 个答案:

答案 0 :(得分:1)

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

Unix时间通常只需几秒钟,但即使您将精度提高到毫秒,您仍然可以使用相同的临时缓存值来存储多个记录,具体取决于从系统读取时间戳的方式的实现细节时钟。

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

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

答案 1 :(得分:1)

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

但是,我担心你的说法

  

我们也绝不会每秒生成多条记录,因此重复项不是问题。

我已经多次听过这个。

  • "我们永远不会有parellel请求"
  • "我们每秒钟都不会收到这么多请求......"

只是警告你,这是诱人的命运,有人会在以后诅咒你。

根据您的评论,您已为冲突添加了检测和退避/重试(关键拒绝),如果您横向扩展,请留意,因为这是您仍可能看到问题的地方

  • 例如,如果你的服务器有时间戳,你可以重叠,即使是毫秒时间戳也会频繁发生冲突 - 毫不像你想象的那么精细,尤其是当你向外扩展时(我发生这种情况时会发生负载均衡)当我尝试根据时间戳和其他一些糟糕的启发式方法创建我们自己的UUID函数时服务器。)
  • 我建议现在解决它,甚至不要通过使用DB中的增量列,UUID或至少其他随机数字段等方式将其打开。