验证数据库中唯一性的最佳实践?

时间:2014-01-21 19:56:53

标签: mysql mysqli unique

我正在创建一个数据库,该数据库需要多个字段才是唯一的,并且想知道在检查唯一性方面哪个方法最便宜

  1. 使用mysqli()调用查询数据库以检查值是否存在?
  2. 使用PHP下载所有条目的文件,然后检查该文件并在之后删除
  3. 将列设置为" Unique"索引
  4. 如果最佳选项(我假设它是)将列设置为唯一,那么如何处理在值已经存在时抛出的错误而不会破坏函数?或者甚至可能吗?

3 个答案:

答案 0 :(得分:4)

  1. 首先查询数据库会带来race conditions的风险。也就是说,您选择SELECT以验证该值是否已存在,因此您可以插入它。但不幸的是,在SELECT和INSERT之间的短暂时刻,其他人会插入并插入您要添加的值。所以你最终还是要抓住错误。

    这似乎不太可能,但有一些古老的智慧:"one in a million is next Tuesday." I.e。当我们每天处理数百万笔交易时,即使是罕见的侥幸也必然会比我们想象的更早发生。

  2. 这是正确的。当一组条目长达1000万时会发生什么? 1亿? 1十亿?此解决方案无法扩展,因此请立即将其排除在外。

  3. 是的,使用UNIQUE约束。尝试INSERT并处理错误。这避免了竞争条件,因为INSERT的唯一检查是原子的。也就是说,在插入它之前,没有人可以在时钟滴答之间插入来添加值。

    有一点需要注意:在MySQL的InnoDB存储引擎中,如果您尝试INSERT并且由于与UNIQUE约束(或其他失败原因)冲突而失败,it doesn't reverse its allocation of the next auto-increment value。未插入行,但会生成并丢弃auto-inc值。因此,如果您经常遇到此类故障,最终可能会跳过主键中的大量整数。我有一个案例,我的客户实际上没有整数,因为他们正在为成功插入的每一行跳过1500个id值。在他们的情况下,我建议使用你的解决方案1,然后只有当他们“非常确定”安全插入时才尝试插入,但是他们必须在竞争条件下处理错误。

    处理错误意味着每次执行SQL查询时检查返回值 。我无法告诉你我在StackOverflow上读了多少问题,程序员无法检查execute()是否返回false,他们想知道为什么他们的INSERT失败了。

答案 1 :(得分:1)

快速回答是让数据库尽可能地执行此操作。

答案较慢取决于您希望如何处理唯一性要求的异常。

如果您永远不需要覆盖唯一性要求,则可以在MySQL中使用UNIQUE索引。然后你可以使用“ON DUPLICATE KEY”来处理异常。

但是,如果您有时需要允许重复,则不能使用UNIQUE键,并且最好使用常规INDEX并在插入之前先查询该值是否存在。

答案 2 :(得分:1)

嗯,最便宜的是一点,用户体验是另一点。

我个人会去查询(如果找到密钥则使用自定义消息)和唯一约束(具有一致的数据库)。所以1 + 3。

但是如果你想要更便宜,只需转到唯一约束,并尝试使用mysqli_error中的错误消息构建一些全面的错误消息。

所以1 + 3或3,但不是2。