通过比较小数秒来防止MySQL重复

时间:2016-03-06 04:16:44

标签: mysql sql timestamp

我花了一个多星期的时间试图看看如何防止重复的mysql条目进入我的表。我怎样才能防止这种情况发生?我不希望用户更新他/她的位置,如果我有一个从最后5秒开始的条目,直到小数秒。例如,我只想要第一个条目,以及忽略后续条目的方法。

我的列类型是时间戳(6)

|         40 |       4 |           5 | 2016-03-05 22:19:57.572771 |
|         41 |       4 |           5 | 2016-03-05 22:19:57.574012 |
|         42 |       4 |           5 | 2016-03-05 22:19:57.589436 |
|         43 |       4 |           5 | 2016-03-05 22:19:57.598959 |
|         44 |       4 |           5 | 2016-03-05 22:19:57.605516 |

我尝试过这样的事情:

"SELECT * FROM checkins WHERE user_id = " + req.body.userID + " AND TIMESTAMPDIFF(SECOND, entered_at, current_timestamp(6)) < 5;"

AND

"SELECT * FROM checkins WHERE user_id = " + req.body.userID + " AND entered_at <= now() AND entered_at >= date_sub(now(),  interval 1 SECOND);"

不幸的是,这些都没有奏效。提前感谢您的任何指导。

修改

为清楚起见,我正在做的是尝试查看某个特定用户是否在最近5秒内创建了一个条目,直到小数秒。如果他有,那么当服务器端的行返回时rows.length > 0将为真。如果实际上rows.length大于零,我将proceedToUpdateUsersLocation变量设置为false。我希望这是一个明确的解释。我试图通过检查过去X秒内表中没有重复项来阻止多个条目。

2 个答案:

答案 0 :(得分:0)

解决方案非常简单,我只是没有必要的SQL技能。我所做的是使用SECONDS_MICROSECONDS函数从curtime(6)中减去4.999999 DATE_SUB()。这是我的最终解决方案。

"SELECT * FROM checkins WHERE user_id = " + req.body.userID + " AND DATE_SUB(curtime(6), INTERVAL 4.999999 SECOND_MICROSECOND) < entered_at;"

谢谢大家的帮助,我希望这对某人有用。

答案 1 :(得分:-1)

我认为几乎所有在插入数据的同一事务之外进行检查的解决方案都会因竞争条件而失败(除非你实现了一些锁定,这可能是一个坏主意,取决于它)。

因此,解决它的一种方法是确保数据库本身可以防止重复。

我建议选择一个规范值来表示您想要合并的所有时间戳,让我们称之为canonical_timestamp并创建一个唯一约束UNIQUE (user_id, canonical_timestamp)

您可以在插入数据之前计算canonical_timestamp,例如int(time()/5)5*int(time()/5)或以任何其他方式符合您对重复记录的目的。

<强>更新

严格地说,当我们收到靠近边境的两个事件时,这个解决方案并没有完全解决问题:

ts = 5 -> canonical_ts = 1
ts = 6 -> canonical_ts = 2