我有一个问题看起来很基本,但很难找到最有效的解决方案。
假设我有这个表,KEYS
表
KEYS
KEY_ID VALUE USED
1 123ASD 1
2 ASD234 0
3 123456 0
我想要一个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连接才能修改该记录,直到它被解锁或连接关闭。