Jea*_*Rey 4 mysql innodb transactions
我目前正在阅读有关 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;
Run Code Online (Sandbox Code Playgroud)
现在假设我想从 2012 年 2 月 15 日到 2012 年 2 月 24 日插入房间 ID 15 的新预订,以下是我认为我应该根据我阅读的内容执行的操作:
开始交易:
START TRANSACTION;
Run Code Online (Sandbox Code Playgroud)插入行
INSERT INTO reservations SET
id_room = 15,
date_from = '2012-02-15',
date_to='2012-02-24',
cancelled='N';
Run Code Online (Sandbox Code Playgroud)检查是否有与我刚刚进行的预订冲突的预订
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();
Run Code Online (Sandbox Code Playgroud)如果不, COMMIT;
别的, ROLLBACK;
问题是,在默认隔离模式(REPEATABLE-READ)下,一旦我开始事务,我就不会看到在这个事务之外进行的任何其他 INSERT。那么,如果在步骤 1) 之后,另一个用户插入了一个冲突的预订,会发生什么?
也许我应该在这种情况下使用 READ-COMMITED?但这不会导致问题吗?感谢您的帮助!
你所拥有的很好,但你需要在你的交易中添加一张表和一个查询。
该表需要为每个 一行id_room。你可能已经有了那张桌子。
所以,在 START TRANSACTION 之后做:
SELECT * FROM room WHERE id_room=15 FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
这将阻止下一个尝试预订同一房间的人,直到您提交或回滚您的事务,只要下一个人也使用此 FOR UPDATE 语法。
http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html