- ベストアンサー
排他制御に関して
こんばんは。お世話になっております。 これまで、質問のタイトルにある「排他制御」というものが「同時アクセスでの不具合を避けるための・・」といった程度の知識しかないまま、DB(MySQL)を利用して会員制のサイトを作っているのですが、全体を見直すべく、いざこの排他制御というものを取り入れようとしてみたところ、手持ちの書籍やこれまで見たサイトでは、ファイルをロック・・・などと言った感じで、DBとの関わりがイメージ出来ず、会員の登録情報の変更ページなどの入力フォームをはじめ、ログインページやDBを用いた検索ページにおいての活用は、どのような手順になるのでしょうか? 些か抽象的な質問になっておりますが、取り掛かりがつかめず、例えばログインページを例にとり、IDとパスワードを入力・DBに問合せ、といった流れでは、どのような手順になるかの全体像だけでもアドバイスいただければと、投函させて頂きました。 お忙しい中恐縮ですが、アドバイスなど頂戴できれば幸いです。宜しくお願い申し上げます。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
DBでは、個々のデータ更新処理(例えば単一のUPDATE文やINSERT文)は、ATOMICに実行されます。ATOMICというのはつまり、殆ど同時に複数のSQL文が実行されても、データが壊れないということです。 これはDBMSが排他処理をやってくれるためです。一方ファイルの場合は、プログラマが明示的に排他処理を書かなければなりません(ANo1さんのいうように。PHPでは通常flock()を使います)。 ただ、ANo2さんの書いたように、明示的にロックを掛ける必要があるケースは存在します。例えばホームページのアクセス数を表示するカウンタの数値の場合は、ロックが必要です。 カウンタでロックをしないと、以下のような不整合が起こる可能性があります。 【Aさん】 【Bさん】 SELECT文でDBのカウンタ値を取得 (カウンタ値=123) SELECT文でDBのカウンタ値を取得 (カウンタ値=123) カウンタ値に1を足す(124) UPDATE文でDBの値を124に変更 カウンタ値に1を足す(124) UPDATE文でDBの値を124に変更 上記では、Aさん、Bさんの2回のアクセスがあったにもかかわらず、カウンタ値は1しか増えません。このような問題は、SELECTする前にロックを掛けて、UPDATEした後にロックを解除することで解決します(BさんのSELECT処理は、Aさんのロック解除まで待たされます)。 ロックを掛ける必要があるのは、カウンタや、商品の在庫数を更新する処理など、一部に限られます。これらは、(1)単一のデータ(カウンタの値や在庫数)を複数アクセスで同時更新する、(2)なおかつSELECTとSELECTした結果に基づく更新処理の両方を実行する、という特徴を持つ処理です。 ご質問にあるような、ログイン処理や会員情報の変更処理は、それらには当てはまらないため、通常ロックを使用する必要はありません。そういう場面でもロックを使用することはできますが、ロックは性能を低下させるので、処理が遅くなる結果を招くだけです。
その他の回答 (2)
- izayoimizuki
- ベストアンサー率41% (84/202)
sjam様の方法はファイルアクセス時の排他制御手法の応用です。 この方法はわかりやすくてで良いのですが問題があります。 なぜならば異なるファイルを排他制御に利用するプログラムまたは 利用しない他のプログラムが存在した場合 排他制御に失敗するからです。 これはあなたが作成したプログラムだけではなく他人が作成したプログラムも含みます。 DBでの排他制御を行いたいのであればDBMSレベルで表単位または行単位でロックすることができます。 1.表の必要な部分をロックを試みる 失敗した場合エラーとし終了 2.トランザクションを発行する 失敗した場合ロールバックしエラーとする 3.ロックを解除する の手順になります。 この場合1.の段階でロック解除の待機といった処理をDBMSがすべて行ってくれるので1回だけのトライで十分です。
補足
izayoimizuki様 はじめまして、こんにちは。貴重なアドバイスを有難う御座います。 イメージしやすいDBにおいてのプログラムの流れ?となる手順に感謝しております。有難う御座いました。
- sjam
- ベストアンサー率41% (26/63)
排他制御用のチェックファイルを調査する。 ↓ 排他制御用のチェックファイルが ★ 真である場合には、1秒待機してやり直す。 但しやり直しが規定回数になれば『失敗』の表示で終了 ★ 偽である場合には、排他制御用のチェックファイルを真にして、次へ進む。 ↓ 必要な処理を行なう。 ↓ 処理が終了したら、排他制御用のチェックファイルを偽に戻して終了 というのが基本の流れです。真偽の判定は、任意の方法です。 例えば、ファイルが有る(真)か無い(偽)かでもいいし ファイルの内容が1(真)かNULL(偽)かでもいいし ファイルのパーミッションが「アクセス不可」(真)か「アクセス可」(偽)かでもいいし (真)と(偽)で区別出来るならファイルをどう利用しても(別にファイルじゃなくても)OKです。
お礼
sjam様 はじめまして、こんにちは。投函後早速の回答を寄せていただき、有難う御座います。 他の皆さんの回答から、今回の私の質問内容とは違うケースのようですが、これも私の質問が悪かったのが原因。有難いアドバイスには感謝しております。今後似たようなケースに対応させていただきたいと思います。有難う御座いました。
お礼
racchoman様 はじめまして、こんにちは。排他処理の流れが曖昧な私ではありましたが、カウンタの流れなども説明いただき、随分とイメージ出来るようになりました。(もちろん完璧ではありませんが) 以前、通常1度のSQL文は排他処理は必要ない・・といった説明をどこかで見ていた記憶がありましたが、その記憶も曖昧であったため、「この場合は必要ないよ」と、言い切って下さったことにホッとしております。 カウンタ処理の流れや在庫管理など、そのケースにおける具体的なアドバイスにも感謝しております。有難う御座いました。
補足
今回アドバイスして下さった皆様へ。(補足欄から失礼します) ポイントとして評価することに心苦しく思いますが、今の私にとって、どれも貴重なアドバイスであった事をお伝えできればと思っております。 ご親切な回答に感謝しております。有難う御座いました。