php - 如何从重负载服务器的表中随机选择唯一值

标签 php mysql

我有一个单列 MySQL 数据库表 ids (id INTEGER PRIMARY KEY AUTOINCREMENT),我在其中按升序存储预生成的唯一 ID。为了从该表中获取随机 ID,我使用此查询:

SELECT id FROM ids ORDER BY RAND() LIMIT 1;

现在我想知道如何确保我获得的 ID 不再被使用。我看到两个选项。一种是从表中删除 id,另一种是添加一个列来跟踪该 id 的使用情况:

DELETE FROM ids WHERE id=?; //where id is the one I got from the previous query

SELECT id FROM ids WHERE used=0 ORDER BY RAND() LIMIT 1; 
UPDATE ids SET used=1 WHERE id=?; //where used is new column with 0 as default value

这两个都只有一个小问题。如果服务器负载很重,那么在从列表中删除(或使用已用列禁用)之前,对随机 ID 的两次查询可能会返回相同的 ID。

事务有帮助吗?

最佳答案

将您的选择和您的更新包装在事务中将起作用。如果您想避免交易以及选择项目和将其标记为不可用之间的竞争条件,您可以先运行 UPDATE。您将需要一种方法让您的每个进程在声明它和删除之间将自己标识为该行的所有者。例如,假设您的 ids 架构是

  • id(整数)
  • 所有者(字符串)

让每个进程选择一个 UUID(或其他适当唯一的东西)并运行以下命令:

  1. UPDATE ids SET owner = $process_id WHERE owner IS NULL ORDER BY RAND() LIMIT 1
  2. SELECT id FROM ids WHERE owner = $process_id
  3. DELETE FROM ids WHERE id = $selected_id(或以其他方式标记它已使用)

第 1 步以原子方式声明该进程的行,以便其他进程无法声明它。第 2 步取出声称的 ID。第 3 步从可用集合中永久删除 ID。如果第 3 步没有删除该行,只是将其标记为已使用,请确保您也清除了 owner,这样您的进程以后就不会再次选择它。

关于php - 如何从重负载服务器的表中随机选择唯一值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30183213/

相关文章:

php - Codeigniter 不正确的 CAPTCHA 图像 src

javascript - 如何在滚动中加载页面

php - 在自定义页面中呈现 drupal 字段小部件

php - 登录时需要传递其中一个字段值

php - 如何从多对多关系中获取数组到对象

php - 尝试从 mysql 的 2 个表中获取数据以显示在 php 中

mysql - 如何将 max() 函数与 update 语句一起使用?

mysql - 如何在同一表的第二个查询中使用一个查询的结果集

php - 在 MYSQL 搜索中使用 URL 参数

php - 如何在 Codeigniter 中记录每个 GET 和 POST 数据?