如何防止两个用户同时访问MySQL表


How can I prevent two users from accessing MySQL table at the same time?

假设我有一个网站,当访问时,它会显示你今天的幸运词。问题是,每个单词都可能只有一个人幸运,所以你需要快速访问网站。下面是一个带有幸运词的示例表:

+---------------------+
| lucky_word          |
+---------------------+
| cat                 |
| moon                |
| piano               |
| yellow              |
| money               |
+---------------------+

我的问题是:如何防止两个(或多个)用户同时访问该表。我假设每个用户从现有表中读取第一个lucky_word,所选单词会立即删除,因此它不会成为下一个用户的幸运词。例如,我想避免cat显示给多个访问者。

我应该使用合适的MySQL查询或PHP代码中的一些行来解决这个问题吗?

您可以在事务中使用锁定读取;例如,使用PDO:

$pdo = new PDO('mysql:charset=utf8;dbname='.DBNAME, USERNAME, PASSWORD);
$pdo->beginTransaction();
$word = $pdo->query('SELECT lucky_word FROM myTable LIMIT 1 FOR UPDATE')
            ->fetchColumn();
$pdo->prepare('DELETE FROM myTable WHERE lucky_word = ?')
    ->execute(array($word));
$pdo->commit();

在MySQL中,您可以锁定表,以防止其他会话读取和/或写入该表。在WRITE锁的情况下,请求锁的第一个会话将保持表,直到它被释放,然后第二个会话将获得它,直到解锁,依此类推。这样就可以确保没有两个会话同时访问或操作相同的数据。

阅读手册中的所有内容:

https://dev.mysql.com/doc/refman/5.6/en/lock-tables.html

在使用特定单词时更新的表中添加一个日期戳怎么样?

然后,您可以使用以下伪sql。。。

select word from words where lastdate <> [today];
update words set lastdate = today where word = [word];

我在类似任务中使用的一种快速方法:

1) 创建一个只有un-field的表"unique_sequence":id->INT AUTOINCREMENT

 CREATE TABLE `erd`.`unique_sequence` (
   `id` INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`));

2) 当用户到达网站时:

INSERT INTO unique_sequence VALUES();
SELECT word FROM lucky_word WHERE id = LAST_INSERT_ID();

由于LAST_INSERT_ID()生成的ID在服务器中按每个连接进行维护,因此它应该是多用户安全的。。。

因此我们可以确信,每个新用户都将获得与lucky_word表中的ID相匹配的唯一ID。