【问题标题】:Preventing MySQL duplicates by comparing fractional seconds通过比较小数秒来防止 MySQL 重复
【发布时间】:2016-03-06 04:16:43
【问题描述】:

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

我的专栏的类型是timestamp(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;"

"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 &gt; 0 将为真。如果事实上rows.length 大于零,我将我的proceedToUpdateUsersLocation 变量设置为false。我希望这是一个明确的解释。我试图通过检查过去 X 秒内表中没有重复项来防止多个条目。

【问题讨论】:

  • 因为我想要表中所有重复的条目,所以我使用 select
  • 好的 - 但首先你谈到了防止重复。选择不会导致重复
  • 哦,我明白你缺少什么了。如果我在服务器上返回 rows.length > 0,这意味着我有重复,所以我将一个变量设置为 false,这样它就不会再次更新用户位置。这个逻辑正在服务器端完成。在这里,我只是查看是否有以前的条目,并通过查看 connection.query 返回的内容来检查。这有意义吗?
  • 并非如此。如果在您检查时出现“上一个条目”怎么办?
  • 这就是为什么我检查表是否在过去 5 秒内有来自该特定用户的任何条目,它只是没有捕捉到同一秒内发生的条目。这就是为什么在我的代码示例中它们都在第 57 秒输入

标签: mysql sql timestamp


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    我认为几乎任何在插入数据的同一事务之外进行检查的解决方案都必然会由于竞争条件而失败(除非您实施一些锁定,这可能是一个坏主意,这取决于)。

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

    我建议选择一个代表您想要合并的所有时间戳的规范值,我们称之为 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
    

    【讨论】:

    • 有趣。我会调查此事并尽快通知您!谢谢!
    猜你喜欢
    • 2015-10-28
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2017-05-09
    • 2014-05-15
    相关资源
    最近更新 更多