たいていの場合は問題ないのですが、
アクセスカウンタ等の更新の激しい物の場合、
file()やfile_get_contents()でファイルを開き、
その内容を元にfopen()・flock()・fputs()等を使って書き込むと、
データが破損してしまう事があります。
これはロック中でもfile()等では開けてしまうのが原因だと思いますが、
file()等を使う際の排他処理はどのようにしたら良いのでしょうか。
ロック中は、fopen()の前で解放されるのを待つ仕様なようなので、
$fp=fopen("ロック用ファイル","r");
flock($fp,LOCK_EX);
~複数のファイルの読み書きを含めた、様々な処理~
fclose($fp);
としてみたのですが、これで排他処理は完璧になるでしょうか?
これまでは、
1. ロック用ファイルが存在する場合、なくなるまでsleep()
2. 空のロック用ファイルを作成
~複数のファイルの読み書きを含めた、様々な処理~
3. ロック用ファイルを削除
としていたのですが、これでは度々破損してしまいました。
「1」と「2」の間で、新しいプロセスが「1」に割り込んで来てしまうせいでしょうか。
そうだとすれば、fopen()とflock()の間でも
同じ事が起きてしまう気がするのですが、どうなんでしょうか。
No.2ベストアンサー
- 回答日時:
おや?だめですか?
では「大人のCGIスクリプト」という本で紹介されていた方法
ファイルが飛ばないようにするには
:ダブルファイルを用いて、両方の更新時間を比較
:更新時間の新しい方のデータを読んで、古い方に書き込む
:よって、データは交互に書き込まれる。
カウンターなら、これだけでもデータが飛ばなくなる
とありました。
あと、以前のQAで、一時ファイルに書き込んでからrenameを使う方法が紹介されてました。
掲示板用ならこちらがよいかもしれません。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1677355
それでもかち合うアクセス数は私にはイメージが付かないので、参考にならないかもしれませんが。
シグナルについてはphpでは、このへんかな?
pcntl_signal -- シグナルハンドラを設定する
http://www.php.net/manual/ja/ref.pcntl.html
お使いのサーバーで有効になってるかどうかも調査する必要がありそうです。
この回答への補足
ご丁寧に有り難う御座います。
今のところはロック用ファイルを用意して、それをflock()する事で破損を防げているようです。
土日に破損する事が多いので、もう少し様子見してみようと思います。
ご教授頂いた交互に書き込む方法も良さそうですね。
ただ、この方法だけでは複数のプロセスで同じデータを扱ってしまう可能性があり、
結局は別途に排他処理を行う必要がありますね。
rename()も同じでファイルを開く際に別途ロックを行わなければいけませんね。
シグナルの件ですが、素人の私には結構難しそうです^^;
色々もっと勉強しないといけないみたいです。
でも、モジュール版ではその関数は使えないようですので、関係ないようですね。
有り難う御座いました。
時間が空いてしまい、申し訳御座いません。
結局、先週の土曜日に破損してしまいました。
見た目、flock()を使った方法に問題は見受けられないんですが・・・。
フラグが残ってしまった場合の対応が曖昧ですが、とりあえずmkdir()も加えてみようと思います。
トップページで使用しているため、出来ればsleepは避けたい気持ちがあるのですが・・・
No.1
- 回答日時:
symlinkかmkdirの方がよいそうです。
参考 web と CGI のひみつ >> 排他処理
http://x68000.q-e-d.net/~68user/webcgi/lock.html
参考URL:http://x68000.q-e-d.net/~68user/webcgi/lock.html
アドバイス有り難う御座います。
これまでにPerlカウンタ等でmkdir()やsymlink()を使っていたのですが、
それでも度々データが破損してしまいました。
参考サイト様によると、シグナルが原因のようですが、
これはモジュール版PHPでも言える事なのでしょうかね。
mkdir()やsymlink()を使った時に
フラグが残ったままになってしまった場合の処理方法がよく分かりません。
単にsleep(1)を5回繰り返してダメならフラグ削除、というのでは問題アリだと思うので。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Perl perlのflock関数でロックをかけたままopen関数で何度もファイルを開きなおすことはできますか 3 2023/05/01 22:25
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
- Visual Basic(VBA) vbaの構文の修正相談(xmlファイルを順に開いてコピペ作業) 1 2023/04/22 01:18
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- Visual Basic(VBA) vbaのエラー対応(実行時エラー7:メモリが不足しています) 4 2023/04/24 00:20
- その他(Microsoft Office) OneDrive Personalについて 1 2022/08/02 18:25
- その他(コンピューター・テクノロジー) <a href="file:///フォルダ名/ファイル名">リンクテキスト</a>について 1 2023/04/06 22:40
- その他(プログラミング・Web制作) python OpenPyXLを使って出力結果をエクセルに書き込み 2 2022/06/04 19:46
- その他(プログラミング・Web制作) pythonでクラスで複数のメソッドを利用する方法 2 2022/04/15 04:17
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
文字コードが混在するテキスト...
-
readfileによる外部HTMLのCSS
-
PHPのメールフォームから別ペー...
-
Smartyのテンプレート作成方法
-
.phpと.incファイルの違いはな...
-
onedrive にexcelファイルをア...
-
透過PNGが透過されない!!
-
Subversionのリポジトリの削除
-
・オブジェクト指向のメリット...
-
別ファイルの変数を呼び出した...
-
PHPのif文でその処理を途中で抜...
-
フォントの色を変えるには?
-
youtubeに音声のみのmp4ファイ...
-
FTPコマンドでディレクトリごと...
-
VBSの「MsgBox」について
-
CFileDialogの最初のディレクト...
-
拡張子php画像をjpg画像等に変...
-
絶対パス?絶対アドレス?意味...
-
PHP+MySQL SQL文を外部ファイル...
-
HYのAM11:00のラップの部分の歌...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
文字コードが混在するテキスト...
-
tmpファイルが消えない
-
is_fileでファイルが存在してい...
-
ログイン認証機能には、どんな...
-
Smartyのテンプレート作成方法
-
index.htmと index.phpが二つある
-
アクセスログの様なCGI
-
onedrive にexcelファイルをア...
-
フォントの色を変えるには?
-
PHPのif文でその処理を途中で抜...
-
別ファイルの変数を呼び出した...
-
.phpと.incファイルの違いはな...
-
CFileDialogの最初のディレクト...
-
FTPコマンドでディレクトリごと...
-
バッチを用いたフォルダの自動移動
-
・オブジェクト指向のメリット...
-
透過PNGが透過されない!!
-
VBSの「MsgBox」について
-
[php初心者]サイトを見てデータ...
-
「@$変数」の「@の意味は?」
おすすめ情報