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

Amy*_*ala 2 mysql unique

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

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

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

Bil*_*win 5

  1. 首先查询数据库存在竞争条件的风险。也就是说,您 SELECT 来验证该值是否已存在,以便您可以插入它。但不幸的是,在 SELECT 和 INSERT 之间的短暂时刻,其他人溜进来并插入了您要添加的值。所以无论如何你最终都必须捕获错误。

    这似乎不太可能,但有一些古老的智慧:“百万分之一是下周二。” 也就是说,当我们每天处理数百万笔交易时,即使是罕见的侥幸也必然会比我们想象的更早发生。

  2. 这是正确的。当条目集有 1000 万长时会发生什么?一亿?1十亿?该解决方案无法扩展,因此请立即将其抛诸脑后。

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

    需要注意的是:在 MySQL 的 InnoDB 存储引擎中,如果您尝试 INSERT 并且由于与 UNIQUE 约束冲突(或其他失败原因)而失败,它不会反转其对下一个自动增量值的分配。该行不会被插入,但会生成并丢弃 auto-inc 值。因此,如果经常发生此类失败,您最终可能会跳过主键中的大量整数。我遇到过一个案例,我的客户实际上用完了整数,因为他们为成功插入的每一行跳过了 1500 个 id 值。在他们的情况下,我建议使用您的解决方案 1,然后仅当他们“非常确定”安全插入时才尝试插入,但随后他们必须处理错误,以防出现竞争条件。

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