7

ユーザーがチケットを購入できる Web サイトを持っていますが、チケットの数量は通常限られており、すぐになくなります。私はエスクロー システムを実装しようとしています。ユーザーが x 数のチケットを希望するをクリックすると、エスクロー状態になります。これにより、クレジット カード情報を入力して購入を完了するまでに数分かかります。

イベント、チケット、エスクローという 3 つの関連テーブルがあります。イベント テーブルの行には、利用可能なチケットの最大数など、イベント自体が記述されています。

チケット テーブルには次のものが保持されます。

user_id : チケットを購入したユーザー

number_of_tickets : 購入したチケットの数

event_id : 関連するイベント

エスクロー テーブルには、次のものがあります。

user_id : チケットを購入中のユーザー

number_of_tickets : 必要なチケットの数

event_id : 関連するイベント

現在、私は 3 つの MySQL クエリを実行しています。1 つは最大チケット、もう 1 つは販売されたチケットの数、もう 1 つはエスクローにあるチケットの数です。次に、次のように計算します。

$remaining_tickets = $max_tickets - $tickets_sold - $tickets_in_escrow;
if ($remaining_tickets >= $tickets_desired)
{
    beginEscrow($user_id, $event_id, $tickets_desired);
}
else
{
    echo "Error:  not enough ticket remain.";
}

私の問題は、複数のユーザーがこのコードを同時に実行できることです。あるユーザーが、すでにエスクローにある数のチケットを読んだbeginEscrow 後に別のユーザーが電話をかけた場合、ショーを過剰販売する可能性があります。

テーブルに InnoDB エンジンを使用しており、 を使用して単一の行をロックする方法を読みましたが、単一の行をSELECT .... FOR UPDATE更新していません。このbeginEscrow関数は、エスクロー テーブルに新しい行を挿入するだけです。$tickets_in_escrow正しいイベント ID を持つすべての行を読み取り、それぞれのチケット数を合計して計算します。

多分私はそれについてすべて間違っていますか?

テーブル全体をロックする必要がありますか?

チケット エスクロー システムを作成したのは私が初めてではありません。私はこの種のことに関するいくつかのチュートリアルを見つけようとして自分自身をグーグルで検索しましたが、打ちのめされました。どんなアイデアでも役に立ちます。

ありがとう!

4

1 に答える 1

10

あなたは自分のデザインに非常に近づいていますが、完全ではありません。

まず第一に、あなたのイベントテーブルはあなたのイベントのためにまだ利用可能なチケットの数を保持する必要があります (あなたがそこに欲しいものに加えて)。

次に、エスクロー テーブルには、エスクローの有効期限が切れる日時を示す DATETIME 列が必要です。チケットがエスクローに入るたびに、その値を設定する必要があります。

第三に、チケットをエスクローに入れるトランザクションは、

  1. イベント行をロックします。
  2. 利用可能なチケット列をお読みください。(十分に利用できない場合は中止します)
  3. エスクロー テーブルに行を挿入する
  4. イベント行を更新して、利用可能なチケット列を減らします。
  5. イベント行のロックを解除します。

第 4 に、販売を完了するアクションでは、エスクロー行を削除し、販売チケット行を挿入する必要があります。これは難しいことではありません。

5 番目に、エスクローのクリーンアップ操作が必要です。これは、有効期限が切れた (過去の有効期限がある) すべてのエスクロー行を探す必要があり、それぞれについて:

  1. 対応するイベント行をロックします。
  2. エスクロー テーブルからエスクローされたチケットの数を読み取る
  3. エスクロー テーブルの行を削除します。
  4. イベント行を更新して、利用可能なチケット列を増やします。
  5. イベント行のロックを解除します。

秘訣は、利用可能なチケットの数を適切に連動させて維持することです。これにより、ユーザー間の競合状態によってイベントが過剰に販売されることはありません。

于 2012-07-01T00:07:22.480 に答える