SELECT和UPDATE语句一个接一个


SELECT and UPDATE statements one after other

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

SELECT room_status FROM rooms WHERE room_number = 'XXX'

然后我运行一个UPDATE查询,将其标记为"不可用":

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

现在,当我运行SELECT查询时,房间是可用的,当我继续执行UPDATE查询时,该房间被其他用户占用。因此UPDATE查询将失败。我希望该房间只由第一个用户占用。我该怎么办?

更新:用户还可能需要预订多个房间。例如,用户选择8个房间。我的代码在第4个房间检查它的状态,当它到达第8个房间时,第一个房间不见了。也可能发生这种情况,当我检查第四个房间时,到目前为止第八个房间已经不见了。

我使用的是:PHP和MySQL

选择行时,需要锁定它们,这样在完成更新之前,其他查询就无法从中读取或写入。在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;        

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

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

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

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

我发现在InsertUpdateDelete上,您需要将with NC(无提交(添加到语句的末尾,否则它将不起作用。

这将有望修复它。