我正在开发一个在线预订系统。在正常过程中,当用户选择在特定时间标记为“可用”的房间并提交他的选择时。现在在后端,为了确认,我运行一个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
答案 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)
我发现在Insert
,Update
和Delete
上您需要在语句末尾添加with NC
(无提交),否则它不会工作。
希望能解决这个问题。
答案 2 :(得分:0)
在这种情况下,请先提交UPDATE
:
UPDATE rooms
SET room_status = 'UNAVAILABLE'
WHERE room_number = 'XXX' AND room_status = 'AVAILABLE'
然后检查受影响的行数。如果受影响的行数为1,那么您已成功预订了房间。
如果其他人提交完全相同的查询,则只有一个会成功。