关于MySQL/PHP中事务(或表锁?)的问题

关于MySQL/PHP中事务(或表锁?)的问题,php,mysql,sql,Php,Mysql,Sql,我有一个问题看起来很基本,但我很难找到最有效的解决方案 假设我有这张桌子,桌子钥匙 我希望有一个API在这里调用get_key.php,它将访问数据库中的最后一个值,used=0,返回JSON格式的键,通过ajax向用户解释,然后将该键标记为在数据库中使用 我看到过关于锁表的想法,但我担心的是,有一个脚本不断地生成密钥并将其插入数据库,而大量用户将请求密钥 要做到这一点,最好的方法是什么?同时还要防止发送重复条目,防止表锁导致网页传递长时间延迟,并且在检索时仍然能够插入 如果你仍然感到困惑,这里

我有一个问题看起来很基本,但我很难找到最有效的解决方案

假设我有这张桌子,桌子钥匙

我希望有一个API在这里调用get_key.php,它将访问数据库中的最后一个值,used=0,返回JSON格式的键,通过ajax向用户解释,然后将该键标记为在数据库中使用

我看到过关于锁表的想法,但我担心的是,有一个脚本不断地生成密钥并将其插入数据库,而大量用户将请求密钥

要做到这一点,最好的方法是什么?同时还要防止发送重复条目,防止表锁导致网页传递长时间延迟,并且在检索时仍然能够插入

如果你仍然感到困惑,这里有一个基本的例子

get_key.php

//not real file just pseudo
//(lock table?)
//SELECT VALUE, KEY_ID FROM `KEYS` WHERE USED = 0 LIMIT 1;
//$key = $response['VALUE']
//echo out key in json format
//$key_id = $response['KEY_ID']
//UPDATE `KEYS` SET USED = 0 WHERE KEY_ID = $key_id;
//(unlock table?)
insert_key.php

//$key = $_GET['value']
//(lock tables?)
//INSERT INTO `KEYS` (VALUE) VALUES ($key)
//(unlock tables?)
我知道在生产环境中的这种设置是非常不安全的,但请尽量简单,以便您能够正确理解我的问题


非常感谢您抽出时间

使用InnoDB或任何其他支持行级锁的引擎。然后,您只需锁定正在选择/更新的有问题的一行,例如

SELECT VALUE, KEY_ID
FROM `KEYS`
FOR UPDATE  // <--- add this row
WHERE USED = 0 LIMIT 1;

... do other stuff

UPDATE `KEYS`
SET USED = 1
WHERE KEY_ID = xxx;

COMMIT;
MySQL将锁定它找到的记录,然后只有这个特定的DB连接才能修改该记录,直到它被解锁或连接关闭

SELECT VALUE, KEY_ID
FROM `KEYS`
FOR UPDATE  // <--- add this row
WHERE USED = 0 LIMIT 1;

... do other stuff

UPDATE `KEYS`
SET USED = 1
WHERE KEY_ID = xxx;

COMMIT;