我有一张资源表(比方说汽车)我想原子地声明。然后,我想知道我刚才声称的资源。
如果每个用户有一个资源限制,我可以执行以下操作:
UPDATE cars SET user = 'bob' WHERE user IS NULL LIMIT 1
SELECT * FROM cars WHERE user = 'bob'
这样,我原子地声明了资源,然后我可以看到我刚刚声明了哪一行。
当'bob'可以声明多辆车时,这不起作用。我意识到我可以获得已经由鲍勃声称的汽车列表,声称另一辆汽车,然后再次SELECT
看看有什么变化,但这感觉很乱。
我想知道的是,是否有某种方法可以查看我刚刚使用上次UPDATE更新了哪些行?
如果失败了,还有其他一些技巧可以原子地声称一行吗?我真的想避免使用SERIALIZABLE
隔离级别。如果我做这样的事情:
1 SELECT id FROM cars WHERE user IS NULL
2 <here, my PHP or whatever picks a car id>
3 UPDATE cars SET user = 'bob' WHERE id = <the one i picked>
这里REPEATABLE READ
会足够吗?换句话说,我可以保证其他一些交易不会声明我的软件在第2步中选择的行吗?
答案 0 :(得分:10)
UPDATE cars SET user ='bob'WHERE id = 123 AND user IS NULL;
更新查询返回已更改行的数量。如果它没有更新任何,你知道该车已被其他人声称。
或者,您可以使用SELECT ... FOR UPDATE。
答案 1 :(得分:2)
update cars
set @id = id, user= 'bob'
where user is null
保证是原子的,@ id会告诉你更新的最后一行是什么。
答案 2 :(得分:1)
您可以使用的一件事是SELECT FOR UPDATE。这将让您进行选择,知道您选择的内容,然后更新这些值。交易完成后将解除锁定。
<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "test");
mysqli_autocommit($link, FALSE);
$result = mysqli_query($link, "SELECT id FROM cars WHERE user IS NULL");
// do something with the results
mysqli_query($link, "UPDATE cars SET user = 'bob' WHERE id = <the one that was picked>");
mysqli_commit($link);
mysqli_close($link);
?>