2012-12-18 9 views
5

これは以前に尋ねられたことがわかりましたが、私はまだ混乱しており、可能であればプログラミングに入る前に問題を避けたいと思います。Mysqlレースの条件を正しく回避する方法

私は、常に100人以上のユーザーがアクティブな内部Webサイトを計画しています。ユーザーはアイテム(0に値を持つdbに挿入されたアイテム)を投稿し、そのアイテムはPHPサイト(dbクエリ)を介して表示されます。ユーザーはボタンを押してそのアイテムをそのアイテムとしてロックするオプションを取得します(そのアイテムの値をIDとして割り当てます)

2人以上のユーザーが同じアイテムを同時に取得しないようにするにはどうすればよいですか。私はC++のようなプログラミングで知っています。彼らはそれのような1つの項目のエントリをロックするmysqlの同等ですか?私はLOCK_TABLESとGET_LOCKや他の多くへの参照を見てきましたので、私はまだ何が最善であろうと非常に混乱しています。

多くの人が1つのボタンを押す可能性があり、複数の人が確認を受けると悲惨なことになります。

これは競合状態の主要な例ですが、mysqlは私にとって外国の領土です。

私は明らかにアイテムを更新し、それが書き込まれていないことを確認しますが、この競合状態が回避されることを保証する最良の方法は何ですか?

ありがとうございます。

答えて

2

これを達成するには、何らかの方法でレコードをロックする必要があります。誰かがボタンこの似たクエリを実行押すと LockedByは0

をデフォルト列を追加:

UPDATEテーブルSETをLockedBy = WHERE LockedBy = 0、ID =。

更新後、影響を受ける行を確認します(php mysql_affected_rows)。値が0の場合、LockedBy列が0でなく他の誰かによってロックされているため、クエリーが何も更新しなかったことを意味します。

希望、これはあなたが行を投稿すると、

+0

なぜ完全に新しい列を作成するのですか?既存の列でこの同じ手法を使用することはできませんでしたか? –

2

を助けNULLに列を設定し、0でない

次に、ユーザがそれを自分自身にするために行を更新するとき、次のように更新します。

UPDATE MyTable SET ownership = COALESCE(ownership, $my_user_id) WHERE id = ... 

COALESCE()は、最初のNULL以外の引数を返します。したがって、あなたと私が同時に更新している場合でも、コミットする最初のものが値を設定します。 2番目の値はその値をオーバーライドしません。

0

あなたは取引

BEGING TRANSACTION; 
SELECT ownership FROM ....; 
UPDATE table .....; // set the ownership if the table not owned yet 
COMMIT; 

を考えることができるし、あなたがエラーをキャッチした場合にも、あなたは、トランザクション間のすべてのクエリをロールバックすることができます!

関連する問題