我目前正在阅读很多有关InnoDB交易的内容,此时我只使用过myISAM表,所以我对这一切并不习惯:
这是我的表格方案:
CREATE TABLE IF NOT EXISTS `reservations` (
`id_reservation` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`id_room` mediumint(8) unsigned NOT NULL,
`date_from` date NOT NULL,
`date_to` date NOT NULL,
`cancelled` enum('Y','N') NOT NULL DEFAULT 'N',
PRIMARY KEY (`id_reservation`),
KEY `id_room` (`id_appartement`)
) ENGINE=InnoDB;
现在假设我要为2012-02-15至2012-02-24之间的房间ID 15插入一个新的预订,这是我认为我应该根据我读到的内容做的:
启动交易:
START TRANSACTION;
插入行
INSERT INTO reservations SET
id_room = 15,
date_from = '2012-02-15',
date_to='2012-02-24',
cancelled='N';
检查是否有与我刚刚提出的预订相冲突的预订
SELECT * FROM reservations WHERE
id_room = 15
AND cancelled = 'N'
AND date_from < '2012-02-24' AND date_to > '2012-02-15'
AND id_reservation <> LAST_INSERT_ID();
如果没有,COMMIT;
其他,ROLLBACK;
问题是,在默认隔离模式(REPEATABLE-READ)中,一旦我启动事务,我就不会在此事务之外看到任何其他INSERT。 那么,如果在步骤1)之后,另一个用户插入了冲突的预留会发生什么呢?
也许我应该在这种情况下使用READ-COMMITED?但这不会导致问题吗? 谢谢你的帮助!
答案 0 :(得分:3)
您拥有的很好,但您需要在交易中添加一个表格和一个查询。
每个id_room
表格需要一行。你可能已经拥有那张桌子了。
所以,在START TRANSACTION之后:
SELECT * FROM room WHERE id_room=15 FOR UPDATE;
这将阻止下一个试图为同一个房间预订的人,直到您执行COMMIT或ROLLBACK,只要下一个人也使用这个FOR UPDATE语法。
http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
答案 1 :(得分:0)
因此,假设我使用php脚本使用PDO和预订系统的交易来访问我的数据库,在那里预订房间一段时间。这些时段为30分钟,但预订时间至少为一小时。因此,一旦它被预订,它也被禁用,因为它只能在30分钟内预订。 假设有两个或更多客户尝试访问并预订某个时间段或之前的一个时间段,第一个会成功吗?其他人将被拒绝,这意味着脚本将结束,或者他们会在第一个完成后等待,如果他确实预订了时间段他们将再次尝试时被拒绝,或者如果他决定不预订房间,第二个将选择并经历相同的事件序列