【问题标题】:Best practice for verifying uniqueness in database?验证数据库唯一性的最佳实践?
【发布时间】:2014-01-21 19:56:52
【问题描述】:

我正在创建一个需要多个字段唯一的数据库,并且想知道在检查唯一性方面哪种方法成本最低?

  1. 使用 mysqli() 调用查询数据库以检查值是否存在?
  2. 使用 PHP 下载所有条目的文件,然后检查该文件并删除
  3. 将列设置为“唯一”索引

如果最好的选择(我假设它是)是将列设置为唯一的,那么当值已经存在而不中断函数时,如何处理抛出的错误?或者这甚至可能吗?

【问题讨论】:

  • 第三个选项是最佳实践。在得到错误表单后,mysql 在您的应用程序中有一个异常来处理它
  • 在任何大小不一的数据库上,“all”都被假定为无限的,永远不能用作解决方案。

标签: mysql unique


【解决方案1】:
  1. 先查询数据库有风险race conditions。也就是说,您 SELECT 以验证该值不存在,因此您可以插入它。但不幸的是,在您的 SELECT 和您的 INSERT 之间的短暂时刻,其他人溜进来并插入了您要添加的值。因此,无论如何您最终都必须捕获错误。

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

  2. 这是正确的。当条目集为 1000 万长时会发生什么?一亿? 1十亿?此解决方案无法扩展,因此请立即忘记它。

  3. 是的,使用 UNIQUE 约束。尝试插入并处理错误。这避免了竞争条件,因为您的 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 失败了。

【讨论】:

  • 配置了异常的 PDO 使得很难错过错误。不确定mysqli 是否有类似的设施。
  • @tadman,是的,确实如此:php.net/manual/en/mysqli-driver.report-mode.php
  • 措辞非常好,先生。我不确定这个项目是否会达到数千万的规模,但我预计它会达到数十万。我什至没有想到你关于比赛条件的第一个场景。
  • 因此,关于组合方法 1 和 3 以相互结合使用,与仅使用方法 3 并交叉手指我没有相同的资源使用情况是否存在显着差异体验过你的客户吗?
  • 这应该是一个非常快速的 SELECT,因为您要在唯一索引中查找特定值。 MySQL 在这方面非常擅长。如果它确实发现了冲突,那么根本不要执行 INSERT。
【解决方案2】:

快速的答案是尽可能让数据库来做。

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

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

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

【讨论】:

  • 没想到ON DUPLICATE KEY...当我们一次只专注于一件事时,简单的事情会如何让我们忘记,这真是令人惊讶。大声笑
【解决方案3】:

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

我会亲自进行查询(如果找到键,则带有自定义消息)和唯一约束(以获得一致的数据库)。所以 1 + 3。

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

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

【讨论】:

  • 我预计这个项目会变得相当强大,所以我肯定会在市场上寻求最快的交互。所以它看起来像 3。
猜你喜欢
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多