4

私は現在、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の新しい予約を挿入したいとします。これが、私が読んだ内容に基づいて行うべきだと思うことです。

  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;

問題は、デフォルトの分離モード(REPEATABLE-READ)で、トランザクションを開始すると、このトランザクションの外部で行われた他のINSERTが表示されないことです。では、ステップ1)の直後に、別のユーザーが競合する予約を挿入するとどうなるでしょうか。

この場合、READ-COMMITEDを使用する必要がありますか?しかし、これも問題につながるのではないでしょうか?助けてくれてありがとう!

4

2 に答える 2

5

持っているものは問題ありませんが、トランザクションに1つのテーブルと1つのクエリを追加する必要があります。

テーブルには、ごとに1つの行が必要id_roomです。あなたはおそらくすでにそのテーブルを持っています。

したがって、STARTTRANSACTIONの直後に次のことを行います。

SELECT * FROM room WHERE id_room=15 FOR UPDATE;

これにより、次の人もこのFOR UPDATE構文を使用している限り、トランザクションをコミットまたはロールバックするまで、同じ部屋の予約をしようとしている次の人がブロックされます。

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

于 2012-09-05T20:53:59.857 に答える
0

たとえば、phpスクリプトを使用して、PDOと、しばらくの間部屋を予約する予約システムのトランザクションを使用してデータベースにアクセスするとします。スロットは30分間ですが、部屋は少なくとも1時間予約されます。したがって、30分間しか予約できないため、時間枠を予約すると、それも無効になります。2人以上の顧客が特定の時間枠またはその前の時間帯にアクセスして予約しようとすると、最初の時間帯は成功し、他の顧客は拒否されます。つまり、スクリプトが終了するか、最初の時間帯が終了した後、彼が実際に予約した場合は待機します。タイムスロット彼らが再試行したとき、または彼が部屋の予約に反対した場合、2番目が選択して同じ一連のイベントを通過するときに拒否されます

于 2012-11-25T08:56:13.150 に答える