ロックをかけるには?

[上に] [前に] [次に]
山からの風 [E-Mail] 1999/03/25(木) 21:33:23
初心者です。http://www2q.biglobe.ne.jp/~terra/cgi/lockfile.htm
上記ホームページにロックファイルのかけ方が記載されています。はたしてここまでやらないと、ロックというものは出来ないのでしょうか。

やま 1999/03/26(金) 00:28:17
どうなんでしょう?
同じく初心者なので、あまり難しいことは分からないのですが、
今使用しているカウンタでは、flockしか使用していません。
これでは完璧ではないのでしょうか?

B-Cus 1999/03/26(金) 00:39:54
ん〜、あそこまでやる必要があるかどうかは疑問です。

> まず、symlink関数が衝突することです。
symlinkは絶対に衝突しません(よね?)。

> それは、データファイルが書き込み可能のパーミッション「666」だからです。
本質的な問題ではないと思います。

> ロックに失敗した場合もunlink($tmpfile);が実行されると言うことです。
本質的な問題ではないと思います。

> これはperlだから許されていますが、他の本格的な開発言語では許されません。
まさか。

ただ、別のファイルに書き込んで最後にリネーム、というのは
考え方としては間違っていないと思います。

にし 1999/03/26(金) 00:48:31
結局のところ、ファイル破壊は確率論の問題ですから・・・
手の込んだことをして重さと引き換えに若干の信頼性向上を得るか、
常套手段で普通の安心を得るか・・・このバランスなんですよね。
ちなみに私はflockです。

#こまめにバックアップする。これが一番です。

やま 1999/03/26(金) 01:48:06
今まで、flockだけで特にファイルが壊れたと言うことは
なかったのですが、とても不安になったのでちょっと
テストしてみました。
2000回カウントアップするプログラムを、フレームで3つ
同時起動させるというものですが、とりあえず成功でした。
もっと回数を増やすと駄目なのかもしれませんが、まあ
カウントくらいなら、これくらいで大丈夫でしょうね。
別に壊れたところで生死にかかわるものではないので・・・。

gama [E-Mail] [HomePage] 1999/03/26(金) 02:56:11
どうも、不確実な経験談

flock が使えないときは、symlink も使えないようだ。
NT での flock は、どうも、壊れる確率が高いようだ。
tera さんとこのは有効だけど、プロセス番号が、つかない環境もあった(^^;;;

共有制御は、悩ましい問題ではあるのであった。

自分とこの Web でも、ちょっと結果を公開しております。

やま 1999/03/26(金) 03:36:20
やはりflockでも完璧とはいかないのですね。
2000回のテストをする前に10000回ずつ合計30000回をやったの
ですが、失敗しているときもありました・・・
まあ、実際にこれだけ集中することはないので、大丈夫と思いますけど。

とほほ 1999/03/27(土) 00:04:35
NTってflock()使えるんでしたっけ・・・Win95では使えないですよね。
flock()は、排他制御(ロック)という観点からは完璧なシステムであり、
それでも壊れるというのは、flock()の使い方がまずいか、排他制御と
は別の問題があるように思えるのですが・・・

やま 1999/03/27(土) 00:48:52
カウントは次のようにしました。たぶんこれで完璧ですね。

open(COUNT,"+<count.txt");
flock(COUNT,2);
$num=<COUNT>;
$num++;
seek(COUNT,0,0);
print COUNT $num;
close(COUNT);

今考えたら、失敗したときはテストの実行方法に問題があったか
もと思います(具体的にどう失敗と思うかは、省略します)。
その後、何回かのテストではうまくいっているので、大丈夫だと
思います。

gama [E-Mail] 1999/03/27(土) 09:57:10
NT で、flock がついている環境がありました。
たぶん、UNIX とは、異なる方法で実装されているのではないかと推測して、Lock の強度をテストしてみました。

通り掛かり 1999/03/27(土) 18:34:29
仕事柄、DB関連のロックとかを扱う身からすると、
** == 1
なんてやってる時点で、う〜ん・・・・・・。
全ては山からの風さんが必要としてるロックの性質にもよります。
向くロック、向かないロックってものがありますから。
万能なロックがあったら私が知りたいです:-)
競合するプログラムが必ずUnlockしてくれるなら、
if (!mkdir($DirectoryNameForLockFlag,"755")) {
とでもするのがお手軽な割りに性能は良いです。
"!"を使わないで、ifの中だけで処理させ、ifに入らなければ、
再度ifに戻させれば、より頑強になります。
一応、CGIプログラムで直接ロックしないで、
別プロセスに飛ばして、そちらで統合的にロックさせたほうが、
安全ではあります。Fork無しのソケットで通信させてやれば、
排他処理も簡単です。

2ヶ月くらい前のUnixマガジンでも軽い記事がありますから、
読むと参考になると思います。

エミュール 1999/03/29(月) 01:21:50
 > > まず、symlink関数が衝突することです。
 > symlinkは絶対に衝突しません(よね?)。
 この場合、「以前のsymlinkが作ったロックファイルが消されてない状態で、symlinkが使われる」っていうのを意味してるんじゃ無いでしょうか?
 また、「絶対に衝突しません(よね?)」というのは、システムを信用し過ぎていますね?・・・いつか足下をすくわれますよ?
 symlinkは一般的に、「衝突」したとしても、そこまで大きな影響を及ぼす様な「重要な関数」としては考えられてないと思います。
 OS作成者及び、Perl作成者が、衝突対策を「重要」と考えてないシステムを、「衝突対策」に使うのは、あまりよろしく無いのでは?

 オレは、flockしか使いません。「flockは不完全だ不完全だ」と、良く耳にするのですが、オレはまだ一度も、ファイルが壊れた事が在りません。
 flockは、衝突対策専用の関数です。たとえ現段階でのロック効果が完全で無くとも、システムが改良される事によって、Perlのプログラム自体を改良せずとも、より高いロックが可能と成るハズですからね。
 また、OS作成者及びPerl作成者は、flockの重要性を、充分に把握しているハズです。つまり、symlinkなんかより、よっぽど信用出来ます。

 同時アクセスより、それよりサーバーダウンの方が、強敵ですよ。
 無駄なコードは、サーバーに負荷を掛けるだけです、負荷を掛けると、サーバーは落ちます。これ、常識ですよね?
 ただ、サーバーダウンの時の為に、テンポラリーファイルを使う事は在ります。

 一応、オレが現在使ってる最高ランクのファイル補完法(笑)は、(←同時アクセス時の為ではなく、サーバーダウン時の為なので・・・)
1、ファイルを+<でOPENし、flock(,2)を掛ける。
2、テンポラリーファイル(時間.プロセス名を元に作る)を作り、それに新しい内容を書き込み、CLOSEする。
3、ファイルにも、同じ内容を書き込む。
4、ファイルをCLOSEし、テンポラリーを消す。
 無駄ばかりのプログラムに見えますし、正に無駄だらけなのですが、これなら、サーバーがダウンして、ファイルの内容が失われても、テンポラリーファイルに、内容が残ります。
 ま、所詮、完全なファイル補完なんて出来ないんですから、これが一番マシだと思うのは、オレだけでしょうか?
(ファイル紛失時は、手作業で、テンポラリーを元に復元します)
 ちなみに、「これだけの補完意義が在るファイル」にしか使ってません。
 「絶対に失われては成らないファイル」の場合のみ、こういう方法を使っては?
(注:ちなみにオレは、UNIXのflockを完全に信頼した上で、これらのコードを書いています。
   ま、サーバーが永久沈黙する事も在りますので、こまめにログを取る事が大切ではないでしょうか?)
 自家用サーバーで、容量に余裕が在るのなら、テンポラリーを消さないという手も。
 ・・・これなら、flockが完全で無かったとしても、大丈夫。


追伸:
 > NTってflock()使えるんでしたっけ・・・Win95では使えないですよね。
 flockは、確かにNTでは使えます。

 > 別プロセスに飛ばして、そちらで統合的にロックさせたほうが、
 専用プロセス作れば、確かに完璧なロックが可能です。
 けど、flockだって、似たような完璧ロックをしてくれてるんじゃ無いの?

通りがかり 1999/03/29(月) 02:03:17
>> 別プロセスに飛ばして、そちらで統合的にロックさせたほうが、
> けど、flockだって、似たような完璧ロックをしてくれてるんじゃ無いの?
さぁ?
内部動作の分かってない関数より、動作のわかってる自作関数:-)
とはいっても、普段はflockやmkdir使います。
負荷評価も大きいですから。ロックのためだけに、
プロセス間通信ってのは結構嫌です。
私の場合、CGIでPOSTした時に、メールで別マシンにも
飛ばした上で、メインデータ自身も一日一回バックアップを
取らせてますから、mkdirやflockで十分です。

今度暇あったら(多分無いけど)ソース見てflock解析しときます。

B-Cus 1999/03/29(月) 02:31:25
> 「以前のsymlinkが作ったロックファイルが消されてない状態で、symlinkが使われる」

ん〜、意味がよくわかりません。

UNIXはマルチタスクOSですが、カーネルレベルで排他的な(絶対に並行して
実行されない)処理ってのがあって、symlinkやmkdirなどのシステムコールは、
排他的であることが保証されてる(既にsymlinkやディレクトリが存在したら、
必ずエラーを返してくれる)と僕は思っているのですが、違うのでしょうか。

 if ( fork() ){
  symlink("symlink","file") || print "error1";
 } else {
  symlink("symlink","file") || print "error2";
 }

は、UNIX系OSでは絶対に error1 か error2 が表示されると思います。

> システムを信用し過ぎていますね?・・・いつか足下をすくわれますよ?

ここではOSのバグなどは考慮に入れていません。

コルン [E-Mail] [HomePage] 1999/03/29(月) 03:49:41
[[解決]]
 オイラは、エミュールさんの意見に賛成ですね。
 ・・・しかし、言葉がちと雑かなぁと。

 >>>まず、symlink関数が衝突することです。symlinkが衝突すると何も返してくれません。これが10回続くと通常のロックなしと、同様に書込んでしまいます。
 >>「以前のsymlinkが作ったロックファイルが消されてない状態で、symlinkが使われる」
 >ん〜、意味がよくわかりません。
 「同時呼び出しでマルチタスク的にsymlinkが衝突する」という本来の意味ではなく、
 「symlinkで作られたファイルが在る状態でsymlinkを使う」って言うのを、ここのページの作者さんが間違って「symlinkが衝突する」と使ってる。って指摘してるんじゃ無いですか?

 >UNIXはマルチタスクOSですが、カーネルレベルで排他的な(絶対に並行して
 >実行されない)処理ってのがあって、symlinkやmkdirなどのシステムコールは、
 >排他的であることが保証されてる(既にsymlinkやディレクトリが存在したら、
 >必ずエラーを返してくれる)と僕は思っているのですが、違うのでしょうか。
 オイラもそう思います。でないと、OSとして成り立ちませんからね。
 ただ、エミュールさんは、symlinkが排他的と保証されてる可能性よりも、flockが排他的と保証されてる可能性の方が高いと言ってるんじゃ無いでしょうか?
 >>システムを信用し過ぎていますね?・・・いつか足下をすくわれますよ?
 >ここではOSのバグなどは考慮に入れていません。
 え・・・と。
 売り言葉に買い言葉・・・でしょうか?
 「OSのバグを考慮に入れないなら、flockを使え」って話に成るのでは?
 それと、信用出来ないシステムは、最初から使わないのでは?
 ・・・あ、違うか。この場合、「自分の想像で、ここまでサポートしてくれてるんだ」とか勝手な思いこみをするな。って言おうとしてるんですね、きっと。

 まぁ要は、「確実に保証されて無ければ成らない所」と、「保証されているであろう所」では、互換性的に前者を使ったプログラミングをしろって事でしょうかね?
 信用よりも信頼に重点を置いてる様ですね。

 >内部動作の分かってない関数より、動作のわかってる自作関数:-)
 まったくです。
 特にC言語の文字列を扱う関数で、バッファのサイズを指定しなくちゃ成らない時とか、「バッファのサイズ」なのか「記憶できる文字の数(バッファのサイズ−1)」なのか、迷いに迷った挙げ句、自分で作る事も在ります。(まぁ、バッファを一つ余分に確保すれば良いだけですけど...)

 >私の場合、CGIでPOSTした時に、メールで別マシンにも
 >飛ばした上で、メインデータ自身も一日一回バックアップを
 >取らせてます
 オイラは全部やってません。
 ファイル補完なんて、必要無いっす。・・・かなりローカルなんで。
 皆の心に発言が残ってりゃぁ、バックアップなんて、必要無いですよね、きっと。
(↑プログラマにあるまじき暴言かも?)
 まぁ兎に角、もしflockにバグが在ったとしても、それは許容範囲内という事で、勝手に解決押しちゃいますよ?

B-Cus 1999/03/29(月) 04:34:25
> 「symlinkで作られたファイルが在る状態でsymlinkを使う」って言うのを、
> ここのページの作者さんが間違って「symlinkが衝突する」と使ってる。
> って指摘してるんじゃ無いですか?

だとしたらsymlinkが悪いわけではないですよね? なら安心です。

>> ここではOSのバグなどは考慮に入れていません。
> 売り言葉に買い言葉・・・でしょうか?

「symlinkにバグがあるかも」って言い出すなら、flockも
同じようにバグがある可能性はあるでしょう。でもそういうことを
言い出すときりがないので、「OSのバグは考慮しません」と書いたわけです。

> ただ、エミュールさんは、symlinkが排他的と保証されてる可能性よりも、
> flockが排他的と保証されてる可能性の方が高いと言ってるんじゃ無いでしょうか?

どうなんでしょう? 根拠がないように思えます。でも、コルンさんや
エミュールさんが、そういうプログラミングの方針を取られることは否定しません。

B-Cus 1999/03/29(月) 05:16:55
書き忘れ書き忘れ。

> たとえ現段階でのロック効果が完全で無くとも、
> システムが改良される事によって、Perlのプログラム自体を改良せずとも、より高い
> ロックが可能と成るハズですからね。

flock も symlink もシステムコールであって、perlはそれを呼んでるだけでしょう。
システムコールが改良されれば、perlやperlスクリプトをいじらずとも品質が
上がるのはどちらも同じですよね。

> symlinkは一般的に、「衝突」したとしても、そこまで大きな影響を及ぼす様な
> 「重要な関数」としては考えられてないと思います。

symlink は vnode の処理あたりでロックしているようです(僕がソースを見る限りでは
そう読めた)。OSの根幹をなすファイルシステムの排他性が、flock に比べて不十分と
言えるだけの根拠はないように思えます。


…でもこういうのって、全て想像と仮定の範囲でしか言えないです(スキルのある人
ならソースを読んで理解できるんでしょうけど、僕には無理)。

ですから、
 > ただ、エミュールさんは、symlinkが排他的と保証されてる可能性よりも、
 > flockが排他的と保証されてる可能性の方が高いと言ってるんじゃ無いでしょうか?
という考え方は、(僕は)無意味なことだと思います。

もちろん実際に「symlinkにこういう問題点がある」ということが明らかに
なれば flock や mkdir に乗り換えます。

とほほ 1999/03/30(火) 00:16:25
昔、UNIXのカーネルで飯を食っていました経験から判断すると・・・
(あくまでBSD系、SystemV系UNIXでの話です。NTは知らない。)

symlink, mkdir, flockはいずれも、ロックを『かける』ことに関して
は完璧。OSがちゃんと排他制御してくれる。

「symlinkで作られたファイルが在る状態でsymlinkを使う」って言う
のを、「symlinkが衝突する」と呼ぶのであれば、この「衝突」を検出
することによってロック権を奪ったか、奪えなかったかを判断している
のであり、衝突は正常動作の範囲。

symlinkとmkdirの違いは、mkdirだと、Windowsでも利用できるという
ことくらいしかない。信頼度は同じ。

ただし、symlink, mkdirはロックを『はずす』時に問題があり、ロッ
ク中にプロセスが異常終了したりすると、ロックファイルが残ったま
まになる。

その点、flockはロックを『はずす』時も完璧で、たとえプロセスが異
常終了しても、OSがストールしても、ロックが残ることは有り得ない。
信頼性ではsymlink, mkdirよりもflockの方が高い。ただしflockは、
UNIXでもサポートしていないOSがある。

しかし、flockでも(symlink, mkdirでも)ファイルが壊れることはあ
る。これは、ロック権を持ったプロセスが中途半端に書き込んでいる最
中に異常終了するなど、ロックとは無関係の原因で発生する。

もちろん、OSやperlのバグは考えていません。バグのことを考えても、
symlink, mkdir, flockのバグの発生頻度は同じようなものでしょう。

> まず、symlink関数が衝突することです。symlinkが衝
> 突すると何も返してくれません。
この1文は、やはり、理解できません。

> ** == 1 なんてやってる時点で、う〜ん・・・・・・。
==1でロックできるかどうかを判断しているのではなく、ロックできたか
どうかを判断しているので、==1でも完璧な処理だと思います。

> "!"を使わないで、ifの中だけで処理させ、ifに入らなければ、 再度
> ifに戻させれば、より頑強になります。
これも、ロックできるかの判断と実際のロック処理の間を短くしようと
いう論理だと思うので、すでにロックできたがどうかを判断する際には
無意味。

・・・・と、まぁ、こんなところです。

コルン 1999/03/30(火) 00:49:53
 >>突すると何も返してくれません。
 >この1文は、やはり、理解できません。
 これ、オイラの経験からすると、「戻り値がundefされてる」とか「''を返す」の様な意味で使われてる可能性が高いと思います。
 オイラはすぐに解りましたが、やはり理解しにくい表現なんですねぇ。

 にしても、flockが完璧って、良かった良かった。うんうん。
 ロックファイルを必要とするのは、flockをサポートしてない場合なんだね。やっぱり。

B-Cus 1999/03/30(火) 03:41:24
> ただし、symlink, mkdirはロックを『はずす』時に問題があり、ロッ
> ク中にプロセスが異常終了したりすると、ロックファイルが残ったま
> まになる。

僕はそれを利用して、symlink("$$",$lockfile)が何度も失敗すると、
if ( ! -d "/proc/".readlink($lockfile) ) で前のプロセスが実行中で
ないことを確認し、前のプロセスが落ちたと判断して、各データの
整合性をチェックしてます(カウンタのデータファイルの中身が
1つ前のデータより減っていないか、とか)。

前のプロセスが落ちたかどうかわかるのは、結構便利だと思ってます。

> これ、オイラの経験からすると、「戻り値がundefされてる」とか「''を返す」の
> 様な意味で使われてる可能性が高いと思います。

ん、これはどういう意味でしょう? symlinkが「戻り値がundefされてる」
「''を返す」場合があるんですか?

> ロックファイルを必要とするのは、flockをサポートしてない場合なんだね。やっぱり。

あと、NFS環境下ですかね。NFSでflockを使えるところと使えない
ところって、どちらが多いんですかね。

コルン 1999/03/31(水) 02:36:02
 >ん、これはどういう意味でしょう? symlinkが「戻り値がundefされてる」
 >「''を返す」場合があるんですか?
 喧嘩を売ってるんでしょうか?(穏やかに話がしたいです、はい。)

 つまりですね、「事実そうである」というのは、「当事者もそう考えた」の証明には成らないって事ですね。
 symlinkは、知っての通り、1か0を返します。
 しかし、当事者が、それを知っていたとは限らない。
 Perlに於いてif文が実行されない式は、''が一般的です。(もちろん、0でも実行されません)
 ですから、「ifで実行されない」=「戻り値が''だ」と、当事者が間違って覚えてる可能性は在ります。

 この当事者は、「1.現在もっとも採用されているロック機能」で、symlinkが0か1かを返すと述べているのに、「2.欠点」でこう言ってます。
 でも、だからと言って、「絶対にそうでない」とは言えませんよね。
 前後の文章を読んでみて下さい。

 >まず、symlink関数が衝突することです。symlinkが衝突すると何も返してくれません。これが10回続くと通常のロック
 >なしと、同様に書込んでしまいます。
 「symlinkの衝突が10回続くと」という所に注目ですね。
 確かに、同期で動かしているので、「まったく同じだけの動作速度で二つのプロセスが動くのなら、10回でも100回でも衝突を繰り返すかも知れない」という考え方も無い事は無いのですが、
 この場合、「symlinkの衝突」ではなく「symlinkの失敗」が10回続いても、「通常のロックなしと、同様に書込んでしまいます。」
 そして、「symlinkの失敗」の可能性の方が、遙かに高い事から考えれば、一目瞭然で、この人は「symlinkの失敗」の事を「symlinkの衝突」と表現しているのです。
 そうなると、当然「symlinkが衝突すると何も返してくれません。」というのは、「symlinkが失敗すると0を返します」という事でしょう。
 ここではsymlinkの戻り値をif文で処理していますので、0で在っても''で在っても大差は在りません。(←これはオイラの方針ではなく、一般的にそう考える人が多いのではないかと言ってるのです。オイラ的には、''と0は全然違います。)
 つまり、if文に渡す場合、「symlinkが失敗すると0を返します」と覚えても「symlinkが失敗すると''を返します」と覚えても、大差は無い訳です。(上に同じく、オイラの方針とは違います)
 そういう訳で、「symlinkが失敗すると''を返します」と書くのを「symlinkが衝突すると何も返してくれません。」と表現しているのでは?

 B-Cusさん、これでもまだ解りませんか?

B-Cus 1999/03/31(水) 07:43:30
> 喧嘩を売ってるんでしょうか?

意味がわからないから質問したまでです。なんでも悪意がこめられていると
思い込むのはやめてください。
 > 売り言葉に買い言葉・・・でしょうか?
これも同じ。いちいちこういうことを言われるのでは、おちおち質問も
できやしない。

> これ、オイラの経験からすると、「戻り値がundefされてる」とか「''を返す」の
> 様な意味で使われてる可能性が高いと思います。オイラはすぐに解りましたが、
> やはり理解しにくい表現なんですねぇ。

要は、
 これ、オイラの経験からすると、(ページの作者は)symlinkが0を返すという
 ことを、「戻り値がundefされてる」とか「''を返す」という(不適切な)
 表現をしてしまっている可能性が高い
ということですね。

あと、もちっと1行を短くしてください。

Yosh 1999/03/31(水) 22:43:50
う〜む、、、ちょっと次元が違かったらすんまへん

セマフォでやるのは、あかんのかなぁ、、、
結局、flockも内部でもセマフォつこーてやってたりして、、、

なにぶん、セマフォ関連の情報が乏しくまともに習得できて
まへんが、、、、どーなんかなぁ

mo [E-Mail] 1999/04/01(木) 01:42:58
> セマフォでやるのは、あかんのかなぁ、、、
セマフォを使っても排他処理できますが、flock に比べて面倒です。
教科書によく載っている P(), V() なんて便利なものはありません。
しかし、semop を使って P(), V() を実装することは可能です。

mo [E-Mail] 1999/04/01(木) 02:29:08
> あと、NFS環境下ですかね。NFSでflockを使えるところと使えない
> ところって、どちらが多いんですかね。
当然、使えないところ。私は、これで、過去なんどもイタイ目にあっています。
NFS 上のファイルに対して flock が確実に動作する保証がないというのは
(UNIX プログラマ間では) 有名な話です。

B-Cus 1999/04/01(木) 03:07:01
これについてさらに詳しい情報をお持ちですか?

例えばサーバ側のOSが〜だったらうまくいかないとか、
クライアント側のOSが〜だったらうまくいくとか、NFSv2なら
うまくいくとか(v2ってありましたよね…たしか)。

いろんな環境を渡り歩いた経験はないので、こういう情報が
あるとありがたいのですが。

# flockの成否は、クライアントに依存するのかサーバに
# 依存するのかも知らないです。

山からの風 [E-Mail] 1999/04/01(木) 18:10:07
[[解決]]
初心者に有り余る情報、アドバイス、有り難うございます。m(_ _)m自分のプロバで、どの方法が有効かテストしたいと思います。

mo [E-Mail] 1999/04/01(木) 21:47:38
> 例えばサーバ側のOSが〜だったらうまくいかないとか、

私も、どの OS の NFS 上のファイルに対して flock が完璧かは知りません。
ただ、過去もっともひどかったのは、flock する度にプロセスがハングってしまい、
しかも kill -9 でも死なないというものでした (OS は IRIX 6.3)。

B-Cus 1999/04/01(木) 23:30:07
moさんも ご存知ないですか、残念。わざわざどうもです。

[上に] [前に] [次に]