• ベストアンサー

排他制御に関して

こんばんは。お世話になっております。 これまで、質問のタイトルにある「排他制御」というものが「同時アクセスでの不具合を避けるための・・」といった程度の知識しかないまま、DB(MySQL)を利用して会員制のサイトを作っているのですが、全体を見直すべく、いざこの排他制御というものを取り入れようとしてみたところ、手持ちの書籍やこれまで見たサイトでは、ファイルをロック・・・などと言った感じで、DBとの関わりがイメージ出来ず、会員の登録情報の変更ページなどの入力フォームをはじめ、ログインページやDBを用いた検索ページにおいての活用は、どのような手順になるのでしょうか? 些か抽象的な質問になっておりますが、取り掛かりがつかめず、例えばログインページを例にとり、IDとパスワードを入力・DBに問合せ、といった流れでは、どのような手順になるかの全体像だけでもアドバイスいただければと、投函させて頂きました。 お忙しい中恐縮ですが、アドバイスなど頂戴できれば幸いです。宜しくお願い申し上げます。

  • PHP
  • 回答数3
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
  • racchoman
  • ベストアンサー率71% (20/28)
回答No.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した結果に基づく更新処理の両方を実行する、という特徴を持つ処理です。 ご質問にあるような、ログイン処理や会員情報の変更処理は、それらには当てはまらないため、通常ロックを使用する必要はありません。そういう場面でもロックを使用することはできますが、ロックは性能を低下させるので、処理が遅くなる結果を招くだけです。

sadacha
質問者

お礼

racchoman様 はじめまして、こんにちは。排他処理の流れが曖昧な私ではありましたが、カウンタの流れなども説明いただき、随分とイメージ出来るようになりました。(もちろん完璧ではありませんが) 以前、通常1度のSQL文は排他処理は必要ない・・といった説明をどこかで見ていた記憶がありましたが、その記憶も曖昧であったため、「この場合は必要ないよ」と、言い切って下さったことにホッとしております。 カウンタ処理の流れや在庫管理など、そのケースにおける具体的なアドバイスにも感謝しております。有難う御座いました。

sadacha
質問者

補足

今回アドバイスして下さった皆様へ。(補足欄から失礼します) ポイントとして評価することに心苦しく思いますが、今の私にとって、どれも貴重なアドバイスであった事をお伝えできればと思っております。 ご親切な回答に感謝しております。有難う御座いました。

その他の回答 (2)

回答No.2

sjam様の方法はファイルアクセス時の排他制御手法の応用です。 この方法はわかりやすくてで良いのですが問題があります。 なぜならば異なるファイルを排他制御に利用するプログラムまたは 利用しない他のプログラムが存在した場合 排他制御に失敗するからです。 これはあなたが作成したプログラムだけではなく他人が作成したプログラムも含みます。 DBでの排他制御を行いたいのであればDBMSレベルで表単位または行単位でロックすることができます。 1.表の必要な部分をロックを試みる 失敗した場合エラーとし終了 2.トランザクションを発行する 失敗した場合ロールバックしエラーとする 3.ロックを解除する の手順になります。 この場合1.の段階でロック解除の待機といった処理をDBMSがすべて行ってくれるので1回だけのトライで十分です。

sadacha
質問者

補足

izayoimizuki様 はじめまして、こんにちは。貴重なアドバイスを有難う御座います。 イメージしやすいDBにおいてのプログラムの流れ?となる手順に感謝しております。有難う御座いました。

  • sjam
  • ベストアンサー率41% (26/63)
回答No.1

排他制御用のチェックファイルを調査する。 ↓ 排他制御用のチェックファイルが ★ 真である場合には、1秒待機してやり直す。  但しやり直しが規定回数になれば『失敗』の表示で終了 ★ 偽である場合には、排他制御用のチェックファイルを真にして、次へ進む。 ↓ 必要な処理を行なう。 ↓ 処理が終了したら、排他制御用のチェックファイルを偽に戻して終了 というのが基本の流れです。真偽の判定は、任意の方法です。 例えば、ファイルが有る(真)か無い(偽)かでもいいし ファイルの内容が1(真)かNULL(偽)かでもいいし ファイルのパーミッションが「アクセス不可」(真)か「アクセス可」(偽)かでもいいし (真)と(偽)で区別出来るならファイルをどう利用しても(別にファイルじゃなくても)OKです。

sadacha
質問者

お礼

sjam様 はじめまして、こんにちは。投函後早速の回答を寄せていただき、有難う御座います。 他の皆さんの回答から、今回の私の質問内容とは違うケースのようですが、これも私の質問が悪かったのが原因。有難いアドバイスには感謝しております。今後似たようなケースに対応させていただきたいと思います。有難う御座いました。

関連するQ&A

  • DB INSERT 時の排他制御について

    初めて投稿するものです。 Java で DB 挿入処理 (会員登録) で悩んでおります。 DB はPostgreSQL8です。 挿入しようとしている会員テーブルは以下のようなレイアウトです。 会員テーブル  ・会員ID 主キー  ・ログインID NOT NULL(*)  ・メールアドレス NOT NULL(*)  ・会員名  ・... ※(*)にはユニーク制約を付けています。 会員IDはPostgreSQLのシーケンスで採番するため、 排他ロックは不要であると思っております。 ですが、ログインIDとメールアドレスは ユニークであるため、排他制御して重複 チェックしなければならないと思っています。 ユニーク制約を張っているため、例外が 発生して判定するというアイデアもあるとは 思いますが、例外で重複判定するのは できれば避けたいと思っております。 例外以外で安全に重複チェックする 場合、どのように排他制御するべきでしょうか? そもそも、排他制御せずに重複チェックを 安全にする方法はあるのでしょうか? ユーザーが多いサイトの場合、テーブルを ロックすると遅くなるような気がします。 ご教授よろしくお願いいたします。

  • JDBCでのトランザクション・排他制御

    初めまして。 まだ初心者の身なのですが質問させてもらいます。 サーブレット・jspでJDBCを使いデータベースとの処理を行って簡単なショッピングサイトのようなものを作っています。 まずsetAutocomit() = falseでトランザクションを開始し データベースのUPDATEを行って、最後に確定する場合comit キャンセルする場合rollbackとしています。 しかし1人のユーザーがトランザクションを行っている場合に他のユーザーからアクセスされた場合にデータベースのトランザクション中の値を取ってきたいのですが、どうしてもトランザクションでUPDATEされる前の値になってしまうのです。 これを防止するのが排他制御というものだというのは分かったのですが 実際のやり方については、結構調べたのですがあまり載っていませんでした。 データベースはMySQLを使っています。 よろしければJDBCでの排他制御についてのアドバイス、もしくは詳しく説明されているサイトなどございましたら是非教えてください。 よろしくお願いします。

  • 同一レコード更新時の排他制御

    Oracle9iです。 C/S開発で、VB.NETで画面を開発します。 DBの更新は、画面よりストアドプロシージャを使って行います。 複数ユーザが同一レコードを同時に参照し、同一レコードに対して更新された場合、参照時の更新日時と異なる場合はエラーとするよう設計されています。(つまり、後更新はエラー) この排他チェックロジックを画面側で実装しようとしておりますが、この排他チェックロジックを画面側で実装せずに、Oracleよりエラーレコードを受け取ることによる排他制御を行うことはできないでしょうか? ご教授のほどよろしくお願いいたします。 また、参考サイトあれば、その紹介だけでも助かります。

  • Access2003での排他制御

    Access2003での排他制御 顧客管理をAccess2003で行っています。 新規で登録するときに顧客IDの重複チェックを[顧客ID_LostFocus]内で DCountを使って行っています。 [cmd登録_Click]で Set db = CurrentDb Set rst = db.OpenRecordset("顧客情報") With rst .AddNew ![顧客id] = me.txt顧客ID.value ![顧客住所] = me.txt顧客住所.value ![顧客TEL] = me.txt顧客TEL.value ・ ・ ・ .Update End With 以上の処理を行っています。 (1)Aさんが新規登録で顧客IDを入力 (2)重複されていないので顧客名や住所の入力をおこなう。 (3)Bさんが同じ顧客IDで新規登録 このケースの場合、 Aさんはまだ登録処理が済んでいない(登録ボタンを押していないためテーブルに反映されていない) ので(3)ではBさんの顧客IDは重複されていません。 Aさんが入力中の顧客IDをBさんが入力した時に「他のユーザーが使用しています」みたいな メッセージを表示するにはどのようにしたらよろしいでしょうか?? 文章が上手く書けなくてもうしわけありません、 何卒宜しくお願いいたします。

  • データベースに書き込むときの排他処理

    ASP3.0 IIS5.0 ASP初心者です。初心者の素朴な疑問なんですが、 ASPで、例えばWebページから入力された情報を、 Accessなどのデータベースに書き込むとき、 排他処理って必要ですよね? 一般的にどうやるのでしょうか? Application変数を使うのでしょうか? データベース自体に排他制御する機能があるのですか? よろしくお願いします。

  • JSPでポップアップウィンドウ制御

    JSPでのポップアップ制御が可能かについて質問いたします。 現在、会員専用ページとして 1:「ログインページ」からID・パスワードを入力。 2:ログインボタンを押す。 3:「会員専用画面」に移動。 という典型的な会員制ページがあります。 そして現在の状況より、3:「会員専用画面」を開く段階でポップアップウィンドウを表示し、会員別に違う情報を表示させる機能を追加したいと思っております。 JSPについて調べてみたのですが、どうやらセッション情報などの絡みなど、難しそうです。 (そもそも情報が少なすぎてここで質問する流れになっております) このような事が出来るかどうか、また方法を伝授していただける方いらっしゃいましたら、よろしくお願いします。

    • ベストアンサー
    • Java
  • セッションに関して

    こんばんは。お世話になっております。 現在、LocalにてDBを連動させたウェブアプリを開発しているのですが、レンタルサーバーにアップさせた際、今まで問題が無かったところに障害が発生してしまいました。 と申しますのも、DBにてIDおよびパスワードを参照してログインする、といった機能を有しており、ログインした際、DBに登録のあるIDなどを$_SESSION[""]= と、セッションに格納してIDを持ち歩いているのですが、他の会員(ここでいうマイページ)のページを覗くと、セッションに格納されたIDが、訪問した会員のIDと入れ替わってしまうのです。 入れ替わってしまうようなコードが存在しているのか?と、確認してはいるものの、そのようなものは見つかりません。 そもそもDBに参照した際、そのDBにあるデータを$_SESSION[""]に代入するだけのコードとなっているのですが、この時点で間違っているのか、単に入れ替わってしまうコードを見落としているだけなのか、を客観的にお聞かせ願えればと思い、投函させていただきました。 お知恵を頂くには言葉足らずなところもありますが、アドバイスのほどいただければ幸いに思っております。宜しくお願い致します。

    • ベストアンサー
    • PHP
  • phpとDBを使いパスワード変更ページ

    いつもお世話になっています。 今回phpとdbで実験的にサイトを作りました。会員制のサイトです。 実験的に作ったものでどこかで公開することはないのでセキュリティなどはガバガバです。 これからしっかり勉強していこうと思いますが、会員制のサイトをログインするにあたりメールアドレスとパスワードでログインしてもらうというようにしました。 パスワードを自分で決めてその内容を登録してログインすることはできたのですが、たまに見かける最初に仮パスワードを発行しその後でパスワード変更ページで変更してもらうというようなページを作りたいです。 このようなページは一体どのように作ればよろしいのでしょうか。 最初に発行した仮パスワードはsha1ファンクションを使って暗号化しています。 最初にdbないのパスワードを参照しその後に変更するようなソースをかけばよろしいのでしょうか とても初歩的な質問ですがお時間があればアドバイスお願いします。

    • ベストアンサー
    • PHP
  • Internet Explorer ではこのページは表示できません

    ある会員系のサイトを作っているのですが、ログインしようとするとie7と8で「Internet Explorer ではこのページは表示できません」 つくりは初歩的で会員DBに問い合わせて合致すればheader関数を用いてTOPページに戻します。そして会員情報を表示するというものです。 firefoxとchromeでは正しく動作するのですが、IEでは表示してくれません。 どのよう対処すればいいでしょうか? 教えてください。よろしくお願いします。

    • ベストアンサー
    • PHP
  • ブラウザの制御について

    お客様からの依頼で簡単なお遊びページを作成しております。(HTML&PHP) 動作的な部分とデザインについては特に問題無いのですが、ブラウザの制御で 行き詰っております。 お客様が用意したメインページから、こちらで作成したページをポップアップで 表示させておりますが、表示させたウインドウのアドレスバー、ステータスバー の非表示(セキュリティの観点から)、ウインドウサイズを固定させたく(マウスでの 操作でウインドウの大きさを変えられなくさせたい)、色々なサイトで情報を集めて 試してみているのですが、上手く出来ません。 IE、Firefox共に同様の制御をさせたいと思っておりますが、何か方法はあるので しょうか? 幾つかのサイトでは、最近のブラウザの仕様として、フィッシングサイト等の対策 の為に、制御が出来なくなっているような記述がありました。 当方、WEBページ作成の経験が無い為、色々とアドバイス、ご意見等を頂ければ 幸いです。 宜しくお願い致します。

    • ベストアンサー
    • HTML