如何在mysql中使用UPDATE原子声明行或资源

时间:2010-03-17 08:17:53

标签: mysql transactions resources atomic

我有一张资源表(比方说汽车)我想原子地声明。然后,我想知道我刚才声称的资源。

如果每个用户有一个资源限制,我可以执行以下操作:

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步中选择的行吗?

3 个答案:

答案 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);
?>