代码之家  ›  专栏  ›  技术社区  ›  OwN

mysql-如果id和timestamp在时间范围内唯一的组合约束,则防止插入记录

  •  0
  • OwN  · 技术社区  · 6 年前

    我有一个场景,其中3个独立的代理正在报告各种主机的正常运行时间状态。如果主机停机并处于脱机状态,则应创建停机记录。不幸的是,由于代理使用相同的信息同时报告,所以我看到了相隔1-2秒的重复条目。

    我在表上为日期时间和主机ID创建了一个唯一约束。因此,它们不能相同。但是,如果来自代理的请求同时或相隔一秒,则可能会创建重复项,尽管代码检查正在查找现有条目(在本例中,如果代理同时报告,则在所有三个实例中都尚未创建条目)。唯一约束也不会阻止重复,因为当php/mysql调用完成处理时,datetime可能在前面或后面1秒…

    那么,处理这种情况的最佳方法是什么?MySQL中有没有一种方法可以指定,如果一个唯一约束(包括日期时间字段)在另一个具有唯一约束的记录的某个时间范围内,则不应该允许插入它?

    我是否需要运行一个在几秒钟内删除条目的作业,或者是否有一种方法可以让MySQL为我做到这一点?

    表结构如下

    条目“主机日期时间”

    条目可能是

    1 121 01/17/2019上午02:38:04

    1 121 01/17/2019 02:38:05上午

    1 121 01/17/2019上午02:36:04

    我想防止插入粗体条目,因为它在插入最后一个条目的1秒内。代码检查将不起作用,因为在检查时可能不存在任何条目。我已经有了一个代码检查来查找一个现有的条目,由于它找不到一个条目,并且可以为每个请求同时运行代码,所以检查失败并表示应该创建一个新条目。

    我的表中有更多的datetime列,但不需要它们来理解这种情况。感谢您的帮助。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Barmar    6 年前

    如果您使用的是MySQL5.7或更高版本,您可以定义一个生成的列,其中包含向下取整到5或10秒范围的时间戳。然后,您可以在该列上定义一个唯一索引,这样,如果您试图在同一时间段内创建两个时间戳为的记录,就会违反约束。

    ALTER TABLE yourTable 
    ADD datetime_10sec INT AS (10 * ROUND(UNIX_TIMESTAMP(datetime)/10)) PERSISTENT, 
    ADD UNIQUE INDEX (host_id, datetime_10sec);
    

    改变两者 10 到您想要使用的时间粒度。