• ベストアンサー

ファイルロックの考え方について教えて下さい。

ファイルロックについてなのですが、調べる程に 混乱してきてしまい、投降させて頂きました。 どうかご指導よろしくお願い申し上げます。 hoge.txt(ログテキスト)があったとします。 Aさんがhoge.txtの内容一覧を開くときに 最初のロックがかかりますよね。 一覧を表示できた時点で一旦ロックが解除され、 次に、修正する内容を選び、修正内容の書き込みを している時点では、hoge.txtは、ロックがかかっていない 状態になっているのですよね? この状態の時に、Bさんがhoge.txtの内容一覧を開き 修正内容を選んだあと、Aさんがhoge.txtへ修正内容を 書き込んだとしたら、Bさんがhoge.txtへ修正内容を 書き込む時は、読み込んだ時点のhoge.txtとは内容が 変っているのだと思うのですが、これは問題ないのでしょうか? この場合、Aさんが、hoge.txtから一覧を参照し、修正内容を選び、 修正の書き込みを実行し終わるまでの時間ずっとhoge.txtはロック状態に あるのが望ましいのでしょうか? でも、参照・修正項目選択・修正書き込み・修正投降までの 時間となると、2、3分では済まない時もありますよね。 この時間ずっとロックというのはあまり良く無いのでは… とも考えております。 修正・閲覧までの数分間をロック状態にしなければ、確かに Aさんが修正しようとしているログを、修正書き込み作業している間に Bさんに、削除されてしまう可能性もある(?)と考えると 一連の作業終了までの間ロックしなくてはいけない、とも思うのですが そうなるとflockなどの機能ですと、一覧を表示して、修正こうもくを 選択した時点で、一旦hoge.txtは閉じられる事になり、ロック解除 状態になるのですよね…? それとも、一旦hoge.txtが閉じられた時は、ファイルサイズ0になるように しておけば、一連の作業中ずっとロック状態になっている、という 事になるのでしょうか…?

  • Perl
  • 回答数8
  • ありがとう数8

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

  • ベストアンサー
  • aton
  • ベストアンサー率47% (160/334)
回答No.5

> この状態の時に、Bさんがhoge.txtの内容一覧を開き > 修正内容を選んだあと、Aさんがhoge.txtへ修正内容を > 書き込んだとしたら、Bさんがhoge.txtへ修正内容を > 書き込む時は、読み込んだ時点のhoge.txtとは内容が > 変っているのだと思うのですが、これは問題ないのでしょうか? 問題あると思います。 Aさんが読み込み(状態0)→Bさんが読み込み(状態0)→Aさんが書き込み(状態0→状態1)→Bさんが書き込み(状態0→状態2) とすると,ファイルの最終状態は状態2ですから,Aさんによる修正は存在しなかったことになり,Bさんの修正だけが残ります。 Aさんにとっては「書き込みが成功したにも関わらず修正が反映されていない」ということになります。 > この場合、Aさんが、hoge.txtから一覧を参照し、修正内容を選び、 > 修正の書き込みを実行し終わるまでの時間ずっとhoge.txtはロック状態に > あるのが望ましいのでしょうか? 全ての人の修正を確実に反映させることが必要なら,答は「yes」です。 > でも、参照・修正項目選択・修正書き込み・修正投降までの > 時間となると、2、3分では済まない時もありますよね。 > この時間ずっとロックというのはあまり良く無いのでは… > とも考えております。 安全性をとるか,利便性をとるかという判断かと思います。 基本的には,できるだけロックを遅らせる(例えば実際に修正すると決めた時点再度ファイルを読み直し,その時点でロックをかける)のだと思います。 別な考え方としては,CVSのように,一つのファイルに二人の人が同時に修正を行ったら,それを同一ファイルの二つの異なる分岐バージョンとして扱うという方法もあります。 これだと長時間のロックは不要になりますが,バージョン分岐を管理する必要が出てきます。 > そうなるとflockなどの機能ですと、一覧を表示して、修正こうもくを > 選択した時点で、一旦hoge.txtは閉じられる事になり、ロック解除 > 状態になるのですよね…? flockではカバーできない,例えば複数CGIにまたがるようなファイルロックを行いたい場合,最も一般的な手法は「ロックファイル」を作ることだと思います。 基本的には, ・ファイルを開く前にロックファイルがあるかどうか確認する ・ロックファイルがあればあきらめる ・なければロックファイルを作成してファイルを開く ・ファイルを閉じるときは,ファイルを閉じてからロックファイルを削除する という感じになります。

sibazuke
質問者

お礼

aton様。 ご指導ありがとう御座いました。 やはり、flockだけでの実装は難しいですね…。 一番無難で簡単です、と紹介されていたので 安易に使おうとした事が迷路の元でした。 ロックファイルを作成する案を使わせて頂く事に致しました。 ロックを掛けたい時に作成するのではなく、最初から 作って置いて、0ならOK1ならロック中です、という旨のメッセージを書く、という方法で行こうと思います。 ご指導、ありがとう御座いました。

その他の回答 (7)

回答No.8

#7さんの詳細と同じようなものですが、開放していますので、 実際にHTMLソースを見ていただければと思います。 #URL露出になってしまいますが・・汗 http://pyukiwiki.daiba.cx/pyukiwiki/PyukiWiki017/ 一部取り出すと・・・ <form action="nph-index.cgi" method="post" id="editform" name="editform"> <input type="hidden" name="myConflictChecker" value="Sun Jul 2 17:33:20 2006"> <input type="hidden" name="mypage" value="あいうえお"> <input type="hidden" name="refer" value=""> <input type="hidden" name="refercmd" value="edit"> <input type="hidden" name="cmd" value="edit"> のような感じになっており、Submitボタンを押した時、時刻とまた比較します。 #実際には、これはファイルのタイムスタンプではなく、別のステータス用のデータベースを持っており、実際にはそちらと比較しています。 ためしに、このページで以下のことをやってみてください。 ・新規ページをつくり、普通に保存する。 ・そのページを右クリック→新しいウィンドウで別窓で編集画面を開く ・更に、そのページを右クリック→新しいウィンドウで別窓で編集画面を開く ・後に開いた画面を少し変更して保存 ・前のページで少し変更して保存 <衝突というメッセージが出ます。

参考URL:
http://pyukiwiki.daiba.cx/pyukiwiki/PyukiWiki017/
回答No.7

そのようなCGIを作った事があります あるサイトのtoppageの一部にhoge.txt等のfileをSSIでincludeしますが 登録されたメンバーが hoge.txtを編集して災害のニュース速報を流すと言うものです。 で、fileロックと自分が編集中に他の人に更新された場合に処理中止を行うことは別物です。 前者はflockやmkdirなどで行い、後者は#2さんの書かれたようにタイムスタンプをつけていました。 細かく書くと 1.hoge.txt読み込み+タイムスタンプ取得 2.編集form表示 (1.のタイムスタンプ情報もhiddenタグで送るようにする)  ここで通常数分間 編集作業を行うがサーバーとのセッションが無いので問題なし 3.form送信ボタンを押す 4.mkdirなどでロック (1. 2.の時点ではロック無しと言うことです) 5.再度hoge.txt読み込み+タイムスタンプ取得して  formで送られた1.で取得されたタイムスタンプと比較して、一致すればhoge.txtへの書き込み  不一致なら「あなたが編集中に他の人に行進されました」と表示してfile書き込みせずエラー処理+ロック解除 6.編集しなおしたければ1.からやり直し出来るようにリンクを表示

sibazuke
質問者

お礼

umasikajiro様。 ご指導ありがとうございました。 細部の詳細まで教えて頂き、とても参考になりました。 一つ、タイムスタンプ取得時の事で疑問に思ったのですが、 最初のhoge.txtを開いた時点で取得したタイムスタンプは、 タイムスタンプ専用のテキストなどを容易して書き込んで置き、 編集作業後、「form」ボタンを押されたときに、hiddenで渡ってきた タイムスタンプとそのタイムスタンプ記述用のテキストの内容と 一致するか否かを判定させる、という方法で良いのでしょうか…?

回答No.6

#2です。 それでは、リネームロックはいかがでしょうか? うちによる実装は、これです。 http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/pyukiwiki/PyukiWiki-Devel/lib/Nana/Lock.pm?rev=1.46&view=markup それ以外にも・・ http://www.din.or.jp/~ohzaki/perl.htm#File_Lock http://homepage1.nifty.com/glass/tom_neko/web/web_04.html http://www.hyuki.com/yukiwiki/wiki.cgi?YukiWikiLock 等があります。

sibazuke
質問者

お礼

ymda様。 何度もご指導ありがとうございます。 リネームによるロックの紹介していただいたサイトさんなど とても勉強になりました。 しかし、長いコードになりますよね。 逆を返せば、それだけロックは重要だと言う事ですよね。 今回flockはなんとなく不都合が出るような気がしましたので、ロックファイルを用意し、0なら書き込みOKで 1ならロック中です、という旨のメッセージが出るような 仕組みで行こうかと考え中です。 ○分以上ロックがかかったままだと自動的にロック解除にする仕組みでうがーとなっておりますが…(泣) 頑張ります。ご指導ありがとう御座いました。

  • moon_night
  • ベストアンサー率32% (598/1831)
回答No.4

やるかやらないかは別として違う考え方。 ・データに修正フラグ、削除フラグを用意しておく。 ・修正しようとするときは修正フラグに時刻を書き込み。 ・そのまま修正せずに終了するとデッドロックになるので、数分で修正フラグを解除する。 (修正フラグを解除された場合に修正しようとした場合(タイムアウトになった場合)は再度最初からやり直し ・削除したものには削除フラグを立てる。 と言うようなことをすれば一応整合性も保たれると思います。 抜けているところもあるとは思いますが。 ファイル全体をロックするのではなく、データ単位でロックするという考え方ですね。 どのようなやり方がいいかは自分の環境に合わせて考える必要がありますね。

sibazuke
質問者

お礼

moon_night様。 いつもご指導ありがとうございます。 そのような方法もあったのですね! ファイルロック、という言葉だけで検索をし 考えあぐねておりましたので、目からうろこでした。 今回は、ロックファイルを作成する方向で行こうと思います。 フラグを立てるという方法は、色々使えそうなので 覚えようと思います。 ご指導、ありがとうございました。

  • kalze
  • ベストアンサー率47% (522/1092)
回答No.3

スペル間違えました。 margeではなく、mergeです。 簡単にいうと、2つのファイルがあったとして、その二つの違いを取得する。 その2つをうち、違う部分が競合してなければ結合するような感じ。 ルールはいろいろありますが。 flockなどのファイルロックは、ファイルへの操作中に他のプロセスからファイルへの操作を行われるのを防ぐためにあるものです。 そのため、ファイルへの操作中以外の保護については、なんらかの方法を検討・実装しなければなりません。 #2様の説明の補足として。 ファイルロックは同時書き込みだけではなく、ファイル操作全般の制御になります。 あるプロセスが書き込みを行っている最中に他のプロセスで読み込まれると問題がある場合があるように(逆もまたしかりですが) そのため、一般的なファイルロック関数は、なにを禁止するかを指定します。 読み込みしているので読み込みは問題ないですよとか、書き込みしているので読み書きしないでねとか。

sibazuke
質問者

お礼

kalze様。 何度もすみません…。 ご指導ありがとうございまいした。 今回は、ロックファイルを容易して、0ならOK1ならロック中ですという旨のメッセージを出す方向で行こうと 思います。 ご指導、ありがとう御座いました。

回答No.2

通常、複数人がいじれるようなサーバー等ではこのような処理をします。 ・hoge.txt を読み込みで開くと同時に、最低でもタイムスタンプを保持する。 ・hoge.txt を書き込む前に、タイムスタンプが同一であるかチェックし、以前の内容と同じであるかチェックする。 これにより、他人が先に編集して書き込みした場合、その後に書き込みしようとする人にわかる仕組みになります。 また、一般のアプリであれば、常時インターバルで(10秒ごとでも)タイムスタンプをチェックすることで、他人が編集したという通知がほぼリアルタイムでできるかと思います。 これらは、適時、アプリ側で制御する必要があります。 ---- ちなみに、OS等に搭載しているファイルロックは、このようなものに対応しているものではありません。 あくまで「同時書込」を阻止するためのロックです。 #OSでなくても、いろんな方法でロックを実装できるんですけどね・・・

sibazuke
質問者

お礼

ymda様。 いつもご指導ありがとうございます。 シンボリックリンクやmkdirなどでhoge.txtの名前自体を変更 したりディレクトリを作成する方法が、ご指導頂いた タイムスタンプ作成にあたると解釈しても良いでしょうか…? 使用したいサーバーで、flockが使用可能な事がわかったので 使ってみたいな、と思い色々検索をした事から今回の疑問に 繋がったのです。 OSはWindowsで、symlinkは使用できないとありました。 ただ、mkdirや(使えたとしても)symlinkは何かのはずみで ロック解除できないままになった時に、手作業で該当のファイルや ディレクトリを削除しなくてはいけない、という注意書きを 見つけ、それは嫌だなぁと感じた事から、安易にflockを 使用しようと決めたものの、ファイルを閉じる=ロック解除に なるという記述も見つけて、今回の疑問がグルグルとなってしまいました。 ファイルロックって奥が深いですね…。

  • kalze
  • ベストアンサー率47% (522/1092)
回答No.1

>書き込む時は、読み込んだ時点のhoge.txtとは内容が >変っているのだと思うのですが、これは問題ないのでしょうか? この懸念は正しいです。 これをどうやって解消するかは、どういうシステムでどれくらいその問題が起こるのかということを検討しての設計の問題となります。 あまり変更頻度が高くないとかで、致命的で無ければ問題なしとすることもあります。 ロックかけっぱなし(もちろんロックは自分で実装する)で解決させることもあります。 一覧を開いたときと、修正を反映させる処理のときとでファイルの内容が変わっていたら修正を反映させずに警告をだすという方法もあります。 また、margeして、修正箇所に衝突がなければ反映させ、衝突があれば警告するという方法もあります。 結局は、どうなってほしいかと、コストとを比較して、どう対策するか次第となります

sibazuke
質問者

お礼

kalze様。 ご指導ありがとう御座いました。 閲覧する人は50人程度で、ファイル操作(書き込み・修正・削除など)をする人は10人足らずなので、 まったくの同時期に、最初書き込みさせて頂いたような ニアミスに近い修正が入る事はまず稀だとは思うのですが それでも、もし万が一!と考え出すとグルグルしてしまいました。 問題なしの方で設計してよいのか、一度相談しなおして みようと思います。 それから、margeとはどういう意味なのでしょうか? 関数リファレンスでは該当のモノが見つからず、英和辞書で しらべてみたのですが「マーガリン」(笑)で…。 よければmargeの意味を教えて頂けないでしょうか。

関連するQ&A

  • 2つのファイルを用いた文字列置換(削除)の方法

    こんにちは。 テキストファイルA.txtに、検索したい文字列を1行ずつ入れておき、別のテキストファイルB.txtのうち、A.txtにある文字が含まれている行を削除するという作業をしたいです。 例えば A.txt AAA BBB B.txt hoge hogeAAAhoge hogeBhoge hogeBBBhoge の場合、 hoge hogeBhoge を出力させたいです。 このような処理ができる方法はないでしょうか?(コマンドやプログラム等)

  • PHPのセッションファイルのロックについて

    PHPにて通常のfileにてセッションを利用するとき セッションファイルはセッションを使用するページが終了するまで ロックされていたりしますか? ページ A セッション開始 → 20秒かかる重い処理 → このあと$_SESSION["hoge"] = 1; ページB セッション開始 → すぐに$_SESSION["hoge"] = 2; ページAを読み込み始めて10秒後にページBを読み込み開始した場合 $_SESSION["hoge"] は 1になりますか2になりますか?

    • ベストアンサー
    • PHP
  • クラスパス配下のファイル名一覧取得

    ある、クラスパスの通ったフォルダ(仮にdir)があったとして そのフォルダ内にあるファイル名一覧を取得したいと考えております。 dir/ ->a.txt ->b.txt ->c.txt 結果:a.txt、b.txt、c.txt ClassLoader クラスなどを用いて取得しようと考えたのですが、 getSystemResource() メソッドなどはファイル名まで指定しないと 取得できないみたいで、現時点で望む処理ができない状態です。 フォルダまでの絶対パスの指定はしたくないため、 Fileクラスも使用できない状態です。 このような処理をやったことがある方は、 どうかご教授お願いいたします。

  • ファイルロックの確認

    PHPで掲示板を作っています。バージョンは5? (php.exeファイルのバージョンは5.2.1.1です。) ファイルロックについて、下記2点を教えてください。 同時書き込みによるログファイルの破損を防ぐため、ロック専用ファイルによるロックとアンロックの仕組みを作りました。 正常に稼動しているか、以下の方法でチェックしました。 1.ブラウザを2つ開く 2.両方とも書き込みボタンを押すだけの状態にする 3.両方のブラウザ(フォーム)の「書き込み」ボタンをすばやく続けてクリックする この方法だと、3で2個のボタンをクリックする間のタイムラグがあり、“同時”書き込みは難しいように思います。 他に方法があるのでしょうか? ////////// ロックファイル:lock/lock.php(755) --<?php --$lockfile = '.lock/lock.txt'; --$fp = fopen($lockfile,"w"); --flock($fp,LOCK_EX); --?> アンロックファイル:lock/unlock.php(755) --<?php --fclose($fp); --?> ロック用ファイル:lock.txt(644) ロックディレクトリ:lock(755) 動作ファイル:bbs.php --<?php --require_once './lock/lock.php'; --掲示板の処理 --require_once './lock/unlock.php'; --?> ロックのファイルを別ディレクトリに置くことは可能でしょうか? 可能であれば、パーミッションはどのようにすればいいのでしょうか? 現状、前述の方法でログが破損するかチェックしても異常ありません。 また、ロック関連の記述を削除してチェックしても異常ありませんので、ロックが正常に稼動しているのかどうか確認できない状態です。 PHPは始めたばかりですので、おかしなことを言っている箇所もあるかもしれませんが、宜しくお願いします。

    • ベストアンサー
    • PHP
  • ロックファイルが消える

    ファイルロックにflockを使っているのですが、複数のファイルを扱うので、データファイルにロックをかけるのではなく別途「ロックファイル」に対してロックをかけています。 データファイルであれば読み書きモードで開く必要がありますが、ロックファイルは中身はどうでも良いので、 open(LOCK,"> $lockfile") or die ~ というように上書きモードで開いて良いとする解説を読んだので、そのようにしています。 しかし、ごくたまにロックファイルが消えてしまう現象が発生します(なかなか再現できずに条件など特定できず)。 あくまでもファイルの中身が壊れるとかいうことではなくて、ファイルそのものが消えます。 そこでお聞きしたいのですが、 1. ロックをかけたファイルが何らかの原因で消えた場合、ロック状態も消失してしまう(他プロセスがロックできてしまう)のでしょうか? 試してみたのですが、  まずプロセスAがロックをかけて  プロセスBが同ファイルにロックをかけようとすると、失敗する  プロセスAがロック解除せずにファイルを削除する  それでもプロセスBはロックに失敗する  プロセスAが(もう存在しないファイルの)ロックを解除(close)する  するとプロセスBはロックに成功する ということは分かったのですが、上記を、プロセスAがファイルを削除した後にプロセスBを動かすと、どういうわけかロックに成功してしまいます。 2. 複数プロセスが同時に上書きモードでopenしようとするのが消える原因なら、ロックファイルであってもやはり読み書きモードで開くべきなのでしょうか。そしてそれなら消えることは無いのでしょうか。 (読み込みモードではロックできないという解説もありました。) 御教授のほどよろしくお願いいたします。

  • オフィス2000→2003 ファイルがロックされて・・・

    オフィス2000~2003へアップグレードしました。 エクセルとワードのファイルがロックされ 解除もできず困っています。OSはXPでサービスパック2です。自宅のデスクトップは問題なく作業できますが、ノートがこのような状態です。 マイクロソフトに修正パッチを探してみましたが 見つけられませんでした。 宜しくお願いします。

  • Perlで フォルダ内の全てのファイルを別のフォルダにコピーするには

    お世話になります。 多分ご存知の方には簡単な話だと思いますが教えていただけませんか。 Aフォルダにあるhoge.txtをBフォルダにコピーしたければ use File::Copy; copy "./A/hoge.txt", "./B/hoge.txt" or die $!; で出来るのはわかっているのですが、Aフォルダにある全てのファイルをBフォルダにコピーするというのはどのようなコードを書いたらよいのでしょう。 ちなみにAフォルダには100以上ファイルがあります。ファイルは全部テキストファイルです。

    • ベストアンサー
    • Perl
  • バッチファイルでのファイル一覧取得

    初心者です。初めてバッチファイルを作成しようと考えていますが、作成方法がわかりません。 環境はWindwsです。 C:\BディレクトリにAというフォルダがありその中に複数のテキストファイルが保存されています。 そのファイルの一覧をBディレクトリ直下のfile_name.txtへ書き込みたいのですが、dirコマンドでファイルの一覧が取得できるのはわかったのですが、ディレクトリ移動してファイルを書き込む方法がわからず困っています。 更にAフォルダには毎日違うテキストファイルが保存されるため、次回バッチを起動した際にはfile_name.txtの中身をクリアして新規に書き込みをしたいと考えています。 初心者で質問内容に不備があるかもしれませんが、ご教授お願いします。

  • 正規表現でファイル名の抽出

    社内の掲示板に属するWebアプリケーションを制作しております。 複数のファイルをアップロードするために、<input type="file" ...> で得たファイルのパスを一時的にリストに表示させる仕様になりました。 そこで、javascriptの正規表現オブジェクトで次のようなフルパスから ファイル名のみを抽出することを考えました。  a: c:\hoge.txt  b: \\foo_server\foo_dir\hoge2.txt a,bから、それぞれ hoge.txt hoge2.txt を得るために、/[^\\].*/によって \\を取り除いた後で/\\.*\..*$/ によって欲しい文字列が得られると考えましたら文字列どころか何も 得られませんでした。 /[^\\].*/までは動いているようです。 オブジェクトの使い方が誤っていると考えているのですが、どの様に 扱えばよいのか皆目見当がつかなくなりました。 大変お手数ですが、ご教示願います。

  • サブルーチンでファイルの内容をハッシュに格納したい。

    次のようなファイルA.txtが有った場合に、ファイルを読み込んで、その内容をハッシュに展開したいと考えています。できれば、サブルーチン化して、引数で渡したハッシュに格納したいのですが、どうすればよいでしょうか? 教えてください。 ----- hoge1 10 hoge2 20 hoge3 30

    • ベストアンサー
    • Perl

専門家に質問してみよう