トップページ⇒php
981コメント337KB

【Perl】ファイルロック(排他処理)について語ろう

レス数が950を超えています。1000を超えると書き込みができなくなります。
0001nobodyさん02/06/23 10:18ID:eY2l+Gw1
どんな環境でも使えて、軽くて、頑丈なロックを考えようじゃありません
08928892006/01/29(日) 07:30:55ID:rUKuWvJe
@dataにデータがある分だけ、ファイルF1とF2に全く同じデータを上書きしたい場合
こんな感じでいいのでしょうか?
上書きする部分だけループにしています。添削してもらえませんか?

open(F1,">$file1")||die();
flock(F1,LOCK_EX);
open(F2,">$file2")||die();
flock(F2,LOCK_EX);
foreach(@data){
($aaa,$bbb)=split(',',$_,2);
print F1 "$aaa,$bbb\n";
print F2 "$aaa,$bbb\n";
}
close(F1);
close(F2);
0893nobodyさん2006/01/29(日) 08:51:40ID:1QlgYllq
1個ロックしときゃいいんじゃないの?
0894nobodyさん2006/01/29(日) 09:17:31ID:???
>>892
書き出したファイルを読み出すことは無いの?
@dataで書き込むデータは常に増えて、減ることはないの?

上二つのどちらかでも該当すると ">"でオープンするのはまずいと思われ。
0895nobodyさん2006/01/29(日) 10:16:26ID:???
定番どころをまとめておくか。

http://search.cpan.org/~nwclark/perl-5.8.7/pod/perlfunc.pod#flock
http://www.kt.rim.or.jp/~kbk/perl-5.8/perlfaq5.html#how_can_i_lock_a_file
http://web.archive.org/web/20040216083853/www98.sakura.ne.jp/~jun/perl/flock.html
http://homepage1.nifty.com/glass/tom_neko/web/web_04.html
http://www.bioinfo.jp/tips.html#flock
http://www.din.or.jp/~ohzaki/perl.htm#File_Lock
0896flock2006/01/29(日) 16:44:40ID:rUKuWvJe
>>893
F1とF2で別々のファイルを開くのに、ロックは1つで良いのですか!?

>>894
このcgiファイルでは、このF1やF2は上書きだけで終了です。
このスクリプトの中でF1およびF2の中に追加項目があったりするので、それを足したのをまた同じF1やF2に上書きするという処理をさせています。

ですので、このファイルでは
>書き出したファイルを読み出すことは無いの?
>@dataで書き込むデータは常に増えて、減ることはないの?
ということは無いです。

ただですね、他のcgiファイルでは読込みがあります。
F1とF2では用途が違うので同じ内容を2つに分けていますが、片方はダウンロードして使いたいのでCSVファイル、もう片方が他で読み込んで使う用途にtxtファイルにしています。
このtxtファイルの方も、他のcgiファイルのスクリプトの中で読み込みはしますが、項目が減ったり増えたりすることはありません。

私は、この部分が変に冗長になっているのではないかと思い、他に良い書き方は無いかと考えてみたのですが
どうしても他の方法が浮かばなかったのでこちらの専門スレに投稿させて頂いた次第です。

良かったら、他の書き方があればご教授願えませんでしょうか?

>>895
ありがとうございます。
その内4つは調べている段階で既読でした。
他のサイトを拝見してきます。
0897flock2006/01/29(日) 17:31:41ID:rUKuWvJe
>>895
今拝見してきたのですが、端的にflockの使い方良し悪しについて述べられているサイトを見つけるのが難しい中、プロセスから易しく書かれたものが見つけられました。
ありがとうございました。

その中にあった
http://web.archive.org/web/20040216083853/www98.sakura.ne.jp/~jun/perl/flock.html#99
の「ゴミ」というところに似た書き方をしているのではと、かなり不安になりました。
特にCSVファイルの方は、サーバからダウンロードして後から情報の閲覧や整理に使いたいので
(@dataに追加するデータは、ある条件を満たすもののみ○、そうでないものは何も書かないというごく簡単なものですが)
○では無いのに○が付いてしまったり、またはその逆などのエラーがあると困ってしまうのです。

ますますもって、このままで良いのか不安になってきました。
ファイルロックについて、このサイトのようにプロセスから細かく記されている書籍などはご存じないでしょうか?
もし、お暇でしたら私のスクリプトの不安箇所の訂正などして頂けたらありがたいのですが....
0898nobodyさん2006/01/29(日) 18:07:38ID:???
>>892
open(F1,"+<$file1")||die();
flock(F1,LOCK_EX);
open(F2,"+<$file2")||die();
flock(F2,LOCK_EX);
...
truncate(F2, tell(F2));
close(F2);
truncate(F1, tell(F1));
close(F1);

($file1,2は既に存在するとして)こんな感じかな。
同じ内容なら、一つのファイルにすることを考えた方がいいかも。
リンク張るとか。

> 「ゴミ」というところに似た書き方をしているのではと、かなり不安になりました。
同じファイルに対して排他的なロックすることで起こるデッドロックだね。
関係があるとしたら、File2とFile1を逆順に排他的にロックするプログラムが有るとき。
そのときはデッドロックを引き起こす可能性がある。
0899nobodyさん2006/01/29(日) 19:15:17ID:???
>>897
lock は結局読み込みから書き込みまでの間に何をするかなんだよな。
(読み込みが含まれるのは読み込んで書き込むまでの間に他の
プロセスが書き込みを行ってしまっていた場合に、新たに書き込む
データが既存のデータを壊してしまうから。)
だから本当は書き込みのところだけ晒されても正しいのかどうかは
判断できない。

ロックで具体的にこうしろというコードが表に出てこないのは
そういう理由もある。
0900はは2006/03/02(木) 23:54:04ID:KQkmhtbv
士ね
0901nobodyさん2006/03/03(金) 01:03:50ID:QWJoZw1q
更新処理はこうしてる。

if (!open(ORI,"$original_file")) { &error; }
if (!open(TMP,"> $tmp_file")) { &error;}
if (!open(LOCK, "$lock_file")){&error;}
flock(LOCK, 2);
while ($_ = <ORI>) {
#各種更新処理
print TMP "$changed_line";
};
close(ORI);
close(TMP);
&lock;
flock(LOCK, 8);
close(LOCK);

sub lock {
$list = `ls $ls`;
@lists = split(/\s+/,$list);
@lists = grep(/\.tmp/,@lists);
@lists = grep(!/$tmp_file/,@lists);
if (@lists) {
if (-e "$tmp_file") { unlink("$tmp_file"); }
&error;
}
if (!rename("$tmp_file","$original_file")) { &error; } ;
chmod 0666,"$original_file";
}

システムが瀕死の状態ん時に(年に1度ぐらい)壊れるが。
0902nobodyさん2006/03/03(金) 02:34:58ID:???
open my $lock, "> $lock_file" or die;
flock $lock, LOCK_EX|LOCK_NB or die;

open my $in, "< $data_file" or die;
open my $out, "> $tmp_file" or die;

while (my $line = <$in>) {
# bra bra bra
. . . . .
print $out $line or die;
}

close $out or die;
close $in;

rename $tmp_file, $data_file or die;

close $lock;

とかでいいんじゃね?
0903nobodyさん2006/03/03(金) 20:34:19ID:QWJoZw1q
>>902
flockを信じればそれでもいけるが、テンポファイルが何らかの障害で生き残った場合
リネームで致命傷。
ユニークなファイル名にしといた方が安全かなと。
0904nobodyさん2006/03/03(金) 22:52:47ID:???
つFile::Temp
0905nobodyさん2006/03/04(土) 01:20:31ID:???
flockを信じればって、じゃあ何を信じりゃいいのさ?
つか、flockすんならテンポラリファイルいらねーだろ。
0906nobodyさん2006/03/04(土) 03:20:16ID:???
use Fcntl qw/:DEFAULT :seek/;

sysopen my $fh, $file, O_RDWR|O_CREAT|O_EXLOCK, 0600 or die $!;
my $sz_file = -s $fh;
sysread $fh, my($buf), $sz_file or die $!;
my @data = split /\n/, $buf;

       :
       :

my $sz_data = length($buf = join "\n", @data);
sysseek $fh, 0, SEEK_SET or die $!;
if ($sz_data < $sz_file) {
  $buf .= "\n" x ($sz_file - $sz_data);
  syswrite $fh, $buf, $sz_file or die $!;
  truncate $fh, $sz_data or die $!;
} else {
  syswrite $fh, $buf, $sz_data or die $!;
}
close $fh;
0907nobodyさんNGNG
>>905
書き出し中に再起動したらどうする?
書き出し中に電源落ちたらどうする?
0908nobodyさん2006/03/04(土) 20:19:13ID:???
排他処理とは関係ないけど、907が言うような障害対策?を
まとめたサイトってありますか?
0909nobodyさん2006/03/04(土) 23:28:46ID:???
>>907
そこまで考える必要があるなら、DB使うよw
0910nobodyさん2006/03/05(日) 00:08:23ID:j4KtSVTy
>>909
そこまで考えるとDB使っても無理。
データは壊れるものと思って、定期的なバックアップは必要。
もちDBのほうが壊れにくいが、それでもMySQLなんて更新多いと壊れる事はある。
このスレはDB使えなくて、それでも極力ファイル破損させたくないって人が対象だろうから、
flock+店舗ファイルが正解なんじゃない?
共用鯖使ってる人が多いだろうけど、そういう鯖は完全に落ちなくてもflock効いてない時結構あったよ。
俺の借りてた鯖の場合は店舗ファイル使って、ずいぶん壊れにくくなったなぁと思うんだけど。

今は自鯖あるから俺もDB使っているけど。
0911nobodyさん2006/03/05(日) 01:35:17ID:???
open my $lock, "> $lock_file" or die $!;
flock $lock, LOCK_EX;
tie @data, "DB_File", $data_file, O_RDWR|O_CREAT, 0666, $DB_RECNO or die $!;
# 更新処理
untie @data;
close $lock;

これで壊れたことないんだけど、何か問題ある?
0912nobodyさん2006/03/05(日) 05:29:10ID:???
>>902
>>911
君らの方法でFAな気が酢
0913nobodyさん2006/03/05(日) 10:29:48ID:???
いやいや、
> LOCK_NB or die;
って、少しは待ってみるとかalarm仕込むとかしようよ。
0914nobodyさん2006/03/06(月) 09:58:45ID:???
>>910
> そこまで考えるとDB使っても無理。
SQLite3 なんかはトランザクション中に再起動や電源断があっても大丈夫って言ってるみたい。
やりかた次第じゃないかな。
0915nobodyさん2006/03/06(月) 20:50:40ID:???
いや、だから、ロックファイル+テンポリネームが答えなんじゃ・・・
0916nobodyさん2006/03/06(月) 21:18:04ID:???
テンポリネームwww
0917nobodyさん2006/07/14(金) 18:34:43ID:???
ここでよいのか分かりませんが。。

このスレを参考にflockでかなりファイルが壊れなくなりました
頭が下がる思いです

で、最近処理速度が気になります。
無論ハード面での影響があるとは思いますがflockで処理するより
MySQLなどを使った方が処理速度は飛躍的に向上しますか?
えろいひと教えて下さい
0918nobodyさん2006/08/18(金) 23:57:42ID:???
>>917
データ構造が巨大かつ複雑で、そこから任意の情報をいやらしい感じに読み書きするような話なのであれば、RDBMS に SQL 渡して丸投げしたほうが *効率は* いいと思う。
餅は餅屋というやつだ。
0919七誌2006/10/27(金) 22:34:40ID:Cj9z7A7l
くぁWせDFRGTYふじKぉP;@:
0920nobodyさん2006/10/27(金) 22:50:51ID:???
もちつけ LとOが入れ替わってるぞ
0921nobodyさん2006/10/28(土) 16:57:21ID:???
すなおにsleepでいいじゃん。
0922nobodyさん2006/11/04(土) 13:00:42ID:???
俺様が勉強してるからあげ
0923nobodyさん2006/11/11(土) 18:19:40ID:umuRe6Kn
結局、一番有効な排他処理は?
0924nobodyさん2006/11/28(火) 09:01:07ID:+OyZsB34
すみませんが、お聞きしたいのですが、
ローカルの環境でカウンターのファイルロックの強度を試すのに、for文で1000回カウンターのファイルにアクセスするスクリプトを作り、
それをタブブラウザで10個開いておいて、全てのタブを再読み込みさせて10000回カウントされているのを見るのは有効な手段でしょうか?
またネットワークにつながっているもう一台のパソコンからも、さらに同時に更新をかけて、20000回カウントされてるかどうか見るのは有効でしょうか?
0925nobodyさん2006/11/28(火) 09:11:11ID:???
「有効な手段」の定義が良くわからんが、タブブラウザ使っても
httpの同時セッション数が既定の2とかだとまったく意味ナサス。
素直にab(apache bench)とか使っとけ。
0926nobodyさん2006/11/28(火) 10:46:03ID:???
テストしてやるからソースを
0927nobodyさん2006/11/28(火) 11:35:28ID:???
テストしてやるからサーバを
0928nobodyさん2006/11/28(火) 13:00:47ID:???
テストしてやるからネットワーク接続を
0929nobodyさん2006/11/28(火) 16:34:07ID:???
テストしてやるからパソコンを
0930nobodyさん2006/11/28(火) 17:08:23ID:???
その前にとりあえずご飯を
0931nobodyさん2006/11/28(火) 19:23:59ID:???
その前に妹を紹介して
0932nobodyさん2006/11/29(水) 00:11:52ID:???
>>924
ロックには二種類しかない、駄目なロックと正しいロックだ。中間はない。
「ロックの強度」などと言うやつが作ったものは駄目なロックである可能性が非常に高い。
0933nobodyさん2006/11/29(水) 03:37:00ID:???
男は黙ってライブステージに立てロックを感じろ
0934nobodyさん2007/01/29(月) 15:46:57ID:MdfhpFZP
今夜ネットつながるのでファイルロックを研究するためこのスレ使いますね。PHPですけど。
0935nobodyさん2007/01/29(月) 17:47:33ID:???
ずんずんちゃっずんずんちゃっ
うぃ〜うぃるうぃ〜うぃるろっきゅ〜
0936nobodyさん2007/01/29(月) 18:21:17ID:???
それ lock じゃなくて rock
0937nobodyさん2007/01/29(月) 18:45:24ID:???
ファイルロックはデータファイル以外にロック用ファイルを用意したほうが楽だから
そうしてるけどデータファイル自体をロックする場合って
一時ファイルに書き出してデータファイル名にリネームした瞬間ロック解除扱いになるんだよね?

そうなるとロック待ちプロセスがデータファイルオープンしてファイルロック中にリネーム
されたらファイルが存在しなくなってファイルハンドルが無効になってファイルロックが偽を返すのかな?
0938nobodyさん2007/01/29(月) 19:04:35ID:???
とりあえずコードで説明して
0939nobodyさん2007/01/30(火) 10:08:22ID:???
>>937
> 一時ファイルに書き出してデータファイル名にリネーム
それ自体は何ら排他処理になっていない。書込途中のプロセス死亡と
いったケースでデータファイルが壊れるのを防ぐ為の手順。

ロックファイルを使わずに排他処理したいなら、

open my $fh, '+<', '/path/to/file' or die $!;
flock $fh, LOCK_EX;
...
close $fh;

のようになる。
0940nobodyさん2007/04/16(月) 16:21:56ID:wXXA2dJL
このスレも残りわずかですね

1つ疑問いいですか?
flockの有効範囲(?)っていうのがいまいち分からなくて。。
同一サーバ内、バーチャルドメインごと、1スクリプトごと。。。??

flockを使って、このスレにある方法を使い正しいロック方法の時だとします

ここまで読んだものから推測するとサーバ内であれば別のスクリプトから呼び出しても効きますよね?(ファイルハンドルが同じなら)

逆に言えばflockを使っているファイルハンドルを別のスクリプトで使ったら解除してしまうってことですか?
レン鯖みたいな共用鯖でよく使いそうなファイルハンドル(INとかOUTとか)でflockを使うと危険なんですかね?


0941nobodyさん2007/04/16(月) 16:38:48ID:???
言語に備わってるファイルロック関数は信用してはいけない
0942nobodyさん2007/04/16(月) 18:29:01ID:???
>>940
Perlのflockは様々な実装があるので、ここではUnix互換OSのflock(2)が
使われた場合とすると、

・flockはOSの機能なので、機能するのはOSの範囲内。
・正しい書き方をすれば、別のプロセスがロックを外すことは無い。
・別プロセスからのflockの開放は可能らしい。
0943nobodyさん2007/04/16(月) 18:31:45ID:???
ファイル構造体にフラグ立ててるわけだからファイルハンドル・別スクリプト云々は考えなくていいっしょ
0944nobodyさん2007/04/16(月) 19:58:57ID:???
mkdirが使えるなら絶対そっちのほうがいいよ
0945nobodyさん2007/04/23(月) 18:26:23ID:???
>942
遅ればせながら�です
0946nobodyさん2007/04/23(月) 20:20:20ID:???
NFSを介した向こう側のファイルを開く時はflockが効かなかったりする。
0947nobodyさん2007/04/26(木) 17:01:49ID:???
>>946
(OSが管理してるので)同じサーバ内でならflockでいい。
別のサーバからのアクセスもロックしたいなら
lockd動かしてfcntlでロックする。
0948nobodyさん2007/04/29(日) 20:50:11ID:QRYQeqJ7
ファイルロックって、馬鹿ですか?
mutex使えよ、アホ
0949nobodyさん2007/04/30(月) 00:26:57ID:???
>>948
Windowsなんて糞なサーバ使うより1000万倍まし。
0950nobodyさん2007/04/30(月) 14:00:30ID:???
>>946
そういうときは、fcntlを使うようにオプションで指示してコンパイルする。
0951nobodyさん2007/04/30(月) 14:26:51ID:???
ファイルロック関数に頼ったロックに頼るべきではない。
独自に考えるべき
0952nobodyさん2007/04/30(月) 17:20:06ID:???
ここはスレタイにあるとおり、「perl」でという制約の元の排他制御に
関する議論をするスレッドなんだよ。
しかもwebprog板なので、サーバーサイド限定だ。
すなわちWin限定の解は採点が低い。
0953nobodyさん2007/04/30(月) 18:09:45ID:???
次スレは言語選ばないべき。過疎ってるから
0954nobodyさん2007/04/30(月) 18:34:21ID:???
PHPも仲間に入れてやってください
0955nobodyさん2007/04/30(月) 22:19:01ID:???
PHPか。
0956nobodyさん2007/05/01(火) 08:41:54ID:???
Perlで1個作って、それを移植するだけだろw
0957nobodyさん2007/05/01(火) 11:06:12ID:???
>>956
ほとんど同じでOKなの?
0958nobodyさん2007/05/03(木) 07:37:55ID:???
5年前のスレかよw
0959nobodyさん2007/11/12(月) 23:00:45ID:???
半年前のレスかよ
0960nobodyさん2007/11/25(日) 15:43:12ID:YhRNGWJK
ageてみるか
0961nobodyさん2008/03/14(金) 20:29:09ID:???
このスレが無限ロックされてるんじゃね?w
0962nobodyさん2008/08/08(金) 02:57:43ID:???
flockにロックIDとかつけてくんないかなー
部分ロックしたいときに困る
0963nobodyさん2008/08/08(金) 02:59:41ID:V81X7ey0
ていうかファイルに対するlockじゃなくて、完全にIDのみで管理するロック機構があれば応用がきくのに
そういうのって何で作られないの?何かわけがあるの?
0964nobodyさん2008/08/08(金) 10:06:25ID:???
ファイルに対してlockしないでなににlockするんだい?

管理はファイルごとに行うんじゃなくてファイルハンドルごとに行うんじゃないかい?
ま、ルールに則って処理しなければlockはいくらでも無視できるけど
0965nobodyさん2008/08/08(金) 19:52:28ID:???
何言ってんのさ。
mkdirとかを用いた方法だって、あくまで"処理のロック"だろ。
その処理ってのがファイルアクセスだったときにファイルロックになるだけでさ。

わざわざロック専用のファイル作ってそれにflockかける場合のこと考えると、「対象としてのファイルがなければロックできない」ってのはどうにも無駄な制限だと思うんだけど。


って書いたけどIDだけでの管理は共用鯖とかだと現実的じゃないな。
0966nobodyさん2008/08/08(金) 20:28:34ID:???
System V IPCのセマフォ使えばいいんじゃない?
perlなら組み込み関数あるし、CPANにもライブラリあるよ。
0967nobodyさん2009/09/07(月) 18:18:57ID:0FwHnD5n
質問です。
apacheのアクセスログの様にとにかく最後尾に追記するだけの場合、排他処理は必要ですか?

use Fcntl;
sysopen(OUT, $FileName, O_WRONLY|O_CREAT|O_APPEND);
print OUT "aaa\n";
close(OUT);

これだけで済めばいいな〜というのは甘い考えでしょうか?
0968nobodyさん2009/09/09(水) 17:11:40ID:???
追記は確か混じった。
0969nobodyさん2009/09/09(水) 17:27:59ID:jdeXznBz
>>968
レスありがとうございます。
後で編集するので書き込まれる順序は特に気にしませんが
一応flock程度はやっておこうかなと思ってます。
0970nobodyさん2009/09/13(日) 16:22:21ID:YylJyw/3
それは print を使うからでは。
一回のシステムコールで書き込まれるようにすれば?
syswrite を使うか、バッファを無効にする。
0971nobodyさん2009/10/08(木) 14:28:23ID:???
書き込みすんだったら、
ロックは必須でしょう?
0972nobodyさん2009/10/12(月) 23:17:19ID:???
このスレでも何度かいわれたし、
http://www.bioinfo.jp/tips.html#append に詳しく書いてある。
確認してみれ。
0973nobodyさん2009/10/19(月) 19:57:43ID:???
システムに依存するけど、どの操作もアトミックにできれば、ロックはいらねぇって話だわな。
0974nobodyさん2010/12/07(火) 00:32:09ID:???
 
0975nobodyさん2010/12/07(火) 00:36:21ID:???
 
0976nobodyさん2010/12/07(火) 00:42:44ID:???
 
0977nobodyさん2010/12/07(火) 00:48:12ID:???
 
0978nobodyさん2010/12/07(火) 00:52:46ID:???
 
0979nobodyさん2010/12/07(火) 01:02:14ID:???
 
0980nobodyさん2010/12/07(火) 01:08:46ID:???
 
0981nobodyさん2010/12/07(火) 01:14:46ID:???
 
レス数が950を超えています。1000を超えると書き込みができなくなります。