2012-09-05 71 views
3

我目前正在讀了很多關於InnoDB的交易,在這個時候,我只使用過的MyISAM表,所以我不是很習慣這一切:InnoDB的交易和客房預訂

這裏是我的表方案:

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; 

現在比方說,我要插入的房間ID 15新的預訂,從2012-02-15到2012-02-24,這裏就是我想我應該基於什麼我讀做:

  1. 開始交易:

    START TRANSACTION; 
    
  2. 插入行

    INSERT INTO reservations SET 
        id_room = 15, 
        date_from = '2012-02-15', 
        date_to='2012-02-24', 
        cancelled='N'; 
    
  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(); 
    
  4. 保留衝突的,如果不是,COMMIT;

  5. 其他,ROLLBACK;

問題是,在默認的隔離模式(可重複讀),一旦我開始交易,我不會看到這個非常事務之外的任何其他INSERT。 那麼,如果在步驟1)之後另一個用戶插入衝突預留,會發生什麼情況?

也許我應該在這種情況下使用READ-COMMITED?但是這不會導致問題嗎? 感謝您的幫助!

回答

3

你有什麼好,但你需要添加一個表和一個查詢到你的交易。

該表格每個id_room需要一行。你可能已經有了這張桌子。

所以,後右START TRANSACTION做:

SELECT * FROM room WHERE id_room=15 FOR UPDATE; 

這將阻止未來的傢伙試圖把在預約同一個房間,直到您提交或回滾您的交易,只要未來的傢伙也使用此FOR UPDATE語法。

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

+0

輝煌,簡單和優雅,謝謝! –

+0

非常聰明的做法:) –

0

所以我們可以說我用PHP腳本訪問使用PDO和交易我的數據庫,您預訂了一段時間的房間預訂系統。插槽是30分鐘的時間,但房間將被預訂至少一個小時。所以一旦它被預訂了之前它也被禁用的時間段,因爲它不能被預訂僅30分鐘。 假設有兩個或兩個以上的顧客嘗試訪問並預訂某個時間段或之前的一個時間段,第一個會成功,其他人會被拒絕,這意味着腳本將會結束,或者在第一個結束後等待,如果他確實已經預訂當他們再次嘗試或在他決定不預訂房間時,他們將被拒絕的時間段,第二次將選擇並經歷相同的事件序列