首页 > 解决方案 > MySQL - 如果 ID 和时间戳在时间范围内唯一的组合约束,则防止插入记录

问题描述

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

我在表上为日期时间和主机 ID 创建了一个唯一约束。因此,它们不可能相同。但是,如果来自代理的请求同时或相隔一秒,尽管代码检查正在寻找现有条目,但可能会创建一个副本(在这种情况下,如果代理同时报告)。唯一约束也不会阻止重复,因为当 PHP / MySQL 调用完成处理时,日期时间可能提前或落后 1 秒......

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

我是否需要运行一项在几秒钟内删除条目的作业,或者有没有办法让 MySQL 以某种方式为我做这件事?

表结构看起来像这样

entry_id host_id 日期时间

条目可能是

1 121 2019 年 1 月 17 日凌晨 02:38:04

1 121 01/17/2019 02:38:05 AM

1 121 2019 年 1 月 17 日凌晨 02:36:04

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

我的表中有更多的日期时间列,但不需要它们来理解这种情况。任何帮助表示赞赏。

标签: mysqldatetimeconstraintsunique

解决方案


如果您使用的是 MySQL 5.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为您要使用的任何时间粒度。


推荐阅读