innodb 交易和房间预订

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 的新预订,以下是我认为我应该根据我阅读的内容执行的操作:

  1. 开始交易:

    START TRANSACTION;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 插入行

    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)
  3. 检查是否有与我刚刚进行的预订冲突的预订

    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)
  4. 如果不, COMMIT;

  5. 别的, ROLLBACK;

问题是,在默认隔离模式(REPEATABLE-READ)下,一旦我开始事务,我就不会看到在这个事务之外进行的任何其他 INSERT。那么,如果在步骤 1) 之后,另一个用户插入了一个冲突的预订,会发生什么?

也许我应该在这种情况下使用 READ-COMMITED?但这不会导致问题吗?感谢您的帮助!

O. *_*nes 5

你所拥有的很好,但你需要在你的交易中添加一张表和一个查询。

该表需要为每个 一行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