SELECT和UPDATE语句一个接一个

时间:2014-05-01 14:33:49

标签: php mysql concurrency

我正在开发一个在线预订系统。在正常过程中,当用户选择在特定时间标记为“可用”的房间并提交他的选择时。现在在后端,为了确认,我运行一个SELECT语句来验证房间的状态是否可用,如下所示:

SELECT room_status FROM rooms WHERE room_number = 'XXX'

然后我运行UPDATE查询将其标记为'UNAVAILABLE':

UPDATE rooms SET room_status = 'UNAVAILABLE' WHERE room_number = 'XXX' AND room_status = 'AVAILABLE'

现在,当我运行SELECT查询时,房间可用,当我继续进行UPDATE查询时,房间被其他用户占用。因此UPDATE查询将失败。我希望房间仅由第一位用户拍摄。我该怎么办?

更新:还可能存在用户必须预订多个房间的情况。例如,用户选择8个房间。我的代码是在第四个房间检查它的状态,当它到达第八个房间时,第一个房间就没了。也有可能发生,当我正在检查第四个房间时,到现在为止第8个房间已经消失了。

我正在使用:PHP和MySQL

3 个答案:

答案 0 :(得分:1)

选择行时,需要锁定它们,以便在完成更新之前,其他查询无法读取或写入。在MySQL中,这可以使用SELECT ... FOR UPDATE语句在事务内部完成:

START TRANSACTION;
SELECT room_status FROM rooms WHERE room_number = 'XXX' FOR UPDATE;

从前一个语句返回的所有行都将被锁定,直到当前事务结束。您现在可以将它们标记为不可用:

UPDATE rooms SET room_status = 'UNAVAILABLE' WHERE room_number = 'XXX';

请记住通过提交更改来关闭事务。这将释放对行的锁定。

COMMIT;        

答案 1 :(得分:0)

我发现在InsertUpdateDelete上您需要在语句末尾添加with NC(无提交),否则它不会工作。

希望能解决这个问题。

答案 2 :(得分:0)

在这种情况下,请先提交UPDATE

UPDATE rooms
SET room_status = 'UNAVAILABLE'
WHERE room_number = 'XXX' AND room_status = 'AVAILABLE'

然后检查受影响的行数。如果受影响的行数为1,那么您已成功预订了房间。

如果其他人提交完全相同的查询,则只有一个会成功。