2017-06-26 7 views
0

このシナリオでは、次の操作の一貫性をどのように許可するかについて苦労しています。コースにサインインできる予約ポータルを開発しています。すべてのコースには多数の直接予約があります:利用可能な予約が終わったら、ユーザーはまだサインすることができますが、待機リストには秋です。並行環境でMYSQLテーブルを正しくロックする方法

これは状況です:たとえば、コースに15スロットがあり、予約しているとします。シンプルなロジックでは、私が予約をしたとき、システムは私がダイレクト予約リスト(利用可能な15のスロットの1つ)または待機リストにあるかどうかを判断する必要があります。総直接予約が可能な合計の予約よりも小さい場合、そうするためには、我々はカウントしなければならない、擬似コードでこのようなものは:

INSERT new_partecipant IN table_partecipants; 
(my_id) = SELECT @@IDENTITY; 
(total_reservations_already_made) = SELECT COUNT(*) FROM table_partecipants WHERE flag_direct_reservation=1; 
if total_reservations_already_made <= total_reservations_available then 
UPDATE table_partecipants SET flag_direct_reservation=1 WHERE id=my_id 

質問です:私は確かであるために、同時実行を管理する方法2つのサブスクリプションは正しく管理されていますか? 1つの予約が残っていて、2人のユーザーが同時に適用される場合、COUNT操作の結果によって両方の要求に同じ結果が与えられ、両方のユーザーがリストに挿入される可能性があります。

ユーザーがサブスクリプション手順を開始した場合、要求が完了する前に誰も同じタスクを完了できないようにするには、正しいロック方法(または同様の手順)は何ですか?の場合には、

INSERT

INSERT INTO table1 (field1, field2, ..., fieldN, flag_direct_reservation) 
SELECT @field1, @field2, ..., @fieldN, ,CASE WHEN (SELECT COUNT(*) FROM sometable WHERE [email protected]_id) > @max_part THEN 1 ELSE 0 END 

のみのサブスクリプション・ステータスを決定するためのUPDATE (:

[OK]を、まだコメントが感謝、我々はロックせずに解決策を見つけたようですサブスクリプション削除)

UPDATE corsi_mytable p1 INNER JOIN 
(
    SELECT COUNT(*) as actual_subscritions 
    FROM mytable 
    WHERE [email protected]_id 
)p2 
SET p1.flag_direct_reservation= CASE WHEN p2.actual_subscritions > @max_part THEN 0 ELSE 1 END 
WHERE p1.id [email protected]_waiting_id; 

このように、操作は1つのSQL文でのみ実行され、トランザクションエンジンは操作の一貫性を保証する必要があります。

+0

しばらくの間活動がありませんでした。あなたは答えを受け入れることができますか? – RaphaMex

答えて

0

このために、テーブル全体をロックすることをお勧めします。行ロックのために移動します。

予約カウンタが15の別のテーブルを1行しか持たず、新しい予約を追加する前にこのカウンタを更新することもできます。 ロックがこの別個のテーブルによって管理されていることを確信しているので、カウンターを気にしない他のシナリオで予約テーブルを更新することができます。

1

テーブルをロックしないでください。代わりに列を試して予約し、失敗した場合は待機リストにそれらを投げてください。例えば:それは右の日だかのように、ここで

UPDATE table_partecipants SET booking_id=? WHERE booking_id IS NULL LIMIT 1 

WHERE句は、他の除外要因を含める必要があります。クエリによって行が正常に変更された場合、予約は機能しました。そうでない場合は、売り切れです。ロックは必要ありません。

ここでbooking_idは、このコースを予約した人に関連付けるために使用できる独自の値です。予約超過のために使用されていないレコードは削除できます。

関連する問題