【MYSQL・PHP】データベースに関する質問です。


データベース名:はてな
テーブル名:人力
カラム:id, 部屋名(Not uniqe)

今回得たい結果:

id | 部屋名
------------------
1 | h2
2 | h1

※h1とh2の順序は逆でも良い

■A,B,C,Dの4人がいると仮定します。
今、AからDが同時にデータの挿入を開始します。

A,Bは部屋名「h1」のデータを挿入。
C,Dは部屋名「h2」のデータを挿入。

しかし、このまま全員が『同時』にデータの挿入を行うと、
if文を書いていたとしても、例えば、

id| 部屋名
----------------
1 | h1
2 | h2
3 | h2

上記のように重複した部屋名が出来てしまうことがあります。

現在、テーブルをロックすることで回避しているのですが、
人数が増えたとき待ち時間がどれくらい増えるか不安です。

解決策があればよろしくお願いします。

※テーブルロックでの待ち時間は、
100人だろうが、1万人だろうが大したことない。
という答えが一番嬉しかったり…

回答の条件
  • 1人2回まで
  • 登録:2008/05/02 09:55:27
  • 終了:2008/05/02 13:08:45

ベストアンサー

id:b-wind No.2

b-wind回答回数3344ベストアンサー獲得回数4402008/05/02 12:59:09

ポイント70pt

ロック処理自体のコストはたいしたことは無いが、テーブルロックだとすべての INSERT が順番にしか実行できないから

件数が多いと件数分の時間がそのままかかってしまうね。


部屋名が UNIQUE になるテーブル、たとえば

CREATE TABLE 部屋 (
  部屋ID integer primary key,
  部屋名 text UNIQUE NOT NULL
);

なんてのを作っておいて、INSERT 実行前に必ず

SELECT * FROM 部屋 WHERE 部屋名 = 'h1' FOR UPDATE

を実行するようにすれば、行レベルのロックですむから部屋が別の人の処理は同時実行できる。


前提として MyISAM では無理なのと部屋名を決める処理はアプリケーション側で工夫しなければいけないぐらいか。

もうちょっと詳細が分かればスマートなやり方もあるのだろうけど。

id:fashion0208

ありがとうございます。

求めている回答にかなり近いものです!

これで締め切りますが、より「スマート」な方法があればコメント欄に是非お願いします。

ポイントを送信したいと思います。

2008/05/02 13:07:29

その他の回答(1件)

id:pahoo No.1

pahoo回答回数5960ベストアンサー獲得回数6332008/05/02 10:55:43

ポイント50pt

まず、異なるユーザーが同時に同じレコードを更新する頻度を推測して下さい。ユーザー数は最大を見込んで計算してください。

それが、数分に1回程度の頻度であれば、現状のようにロックをかけることで十分だと思います。ロック処理で待たされることは無いはずですから。


同時更新が毎秒発生するようだと、別の対応策が必要です。

たとえばメッセージキューを使う方法があります。MySQL 5.1 限定ですが、「Q4M - MySQL 上で動作するメッセージキュー」で紹介されています。PHPからも利用できます。


ただ、キューが満杯になるケースもあり得るわけで、できれば、同時更新レコードが発生しないようなDB設計(または業務設計)をした方が良いと思います。

id:fashion0208

有り難う御座います!

詳細を省いてしまったせいで、回答し辛くしてしまい申し訳ありませんでした。

早速頻度の推測から始めたいと思います。

2008/05/02 13:05:18
id:b-wind No.2

b-wind回答回数3344ベストアンサー獲得回数4402008/05/02 12:59:09ここでベストアンサー

ポイント70pt

ロック処理自体のコストはたいしたことは無いが、テーブルロックだとすべての INSERT が順番にしか実行できないから

件数が多いと件数分の時間がそのままかかってしまうね。


部屋名が UNIQUE になるテーブル、たとえば

CREATE TABLE 部屋 (
  部屋ID integer primary key,
  部屋名 text UNIQUE NOT NULL
);

なんてのを作っておいて、INSERT 実行前に必ず

SELECT * FROM 部屋 WHERE 部屋名 = 'h1' FOR UPDATE

を実行するようにすれば、行レベルのロックですむから部屋が別の人の処理は同時実行できる。


前提として MyISAM では無理なのと部屋名を決める処理はアプリケーション側で工夫しなければいけないぐらいか。

もうちょっと詳細が分かればスマートなやり方もあるのだろうけど。

id:fashion0208

ありがとうございます。

求めている回答にかなり近いものです!

これで締め切りますが、より「スマート」な方法があればコメント欄に是非お願いします。

ポイントを送信したいと思います。

2008/05/02 13:07:29
  • id:KirakiraHikaru
    「部屋名」にユニーク属性を設定して、重複した部屋名が挿入できないようにするのではダメなのでしょうか?
    7.unique
    http://www.ei.nagano-nct.ac.jp/text/4J/SQL/FieldAttributes.html
  • id:fashion0208
    fashion0208 2008/05/02 11:01:40
    >KiraKiraHikaru様
    今回のケースだと、ユニーク属性を指定すれば良いと思われるかもしれませんが、
    実際のケースではState(初期値:0)というカラムがあり、
    このStateが終了状態(値:1)になったときは、再度同じ部屋名を作ることができるという制限をかけているのです。
    そのため、質問本文にもありますが、ユニーク属性はないものとして回答をお願いしております。

    コメント有り難う御座います。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません