3

私のPHPコードでは、ファイルを開いてテキストを追加します。私はこのコードを使用します:

$ourFileHandle = fopen($ourFileName, 'a') or die("can't open file");

これは、PHPページがロードされたときに発生します。2人が同時にPHPページをロードするとどうなりますか?このコードは、1人の人に対して機能し、もう1人の人に対しては実行されdie()ますか?一般的に、いつfopen失敗する可能性がありますか?

ありがとう。

4

3 に答える 3

6

TL;DR-データベースを使用するだけ

これは単純な主題ではありません。ほとんどのシステムではすべてのリクエストでファイルを開くことができ、複数のスクリプトが同時にファイルに書き込むことができる可能性があるため、複数の同時リクエストに対して実行していることは間違いなく期待どおりに機能しません。これを行うと、ファイルにガベージが含まれます。

このための可能な回避策は多種多様ですが、ここでは、私が最も実行可能であると考える3つについて説明します。

  1. データベースを使用します。これは、あなたがやろうとしていることに対する最善の解決策であることはほぼ間違いありません。RDBMSは、ビートをスキップすることなくこれらの同時実行性の問題をすべて処理します。これを行うと、同時実行性に問題が発生することはありません。

  2. を使用してファイルの排他ロックを要求しますflock()。この関数は、アドバイザリロックを使用して、複数の同時プロセスが同時にファイルにアクセスするのを防ぎます。これは、複数のPHPプロセスのニーズに適合しますが、PHPが使用するのと同じタイプのアドバイザリロックシステムをサポートしていない場合、他の外部プログラムでは機能しない可能性があります。
    flock()ファイルのロックが取得されるまで「ブロック」します。これは、リクエストの同時実行性に悪影響を与えることを意味します。一度に1つのリクエストのみがファイルに書き込むことができます。さらに、ロックが要求された順序で提供されることを保証するものではないため、後で到着した他の要求が満たされている間に、1つの要求がファイルのロックを取得しない状況になる可能性があります。

  3. バックグラウンドプロセスを使用してファイルアクセスを処理し、スクリプトがプロセスと通信するようにします。これは、1)の独自のバージョンをロールバックするようなもので、気弱な人向けではありませんが、正しく実行すると大きな効果を発揮します。
    このモデルを使用すると、何らかの形式のプロセス間通信を使用して、ファイルに書き込む必要のあるデータをバックグラウンド(永続)プロセスに中継します。次に、このバックグラウンドプロセスがファイルへの書き込みを管理し、メッセージが完全に正しい順序で書き込まれるようにします。通常(PHPを使用する場合)、このようなIPCはソケットを使用して実装されます。これは簡単ではありませんが、潜在的に最も強力なソリューションです。


より一般的な観点からは、fopen()通常、アクセス許可の問題または低レベルのオペレーティングシステムの問題が原因で失敗します。OSが、他のプログラムがファイルを開くのを防ぐ「真の」ロックメカニズムを提供することも可能です。fopen()ただし、多くの可能性があるため、真の「理由のリストは失敗する可能性があります」を提供することは困難です。

明らかに、読み取りモードでファイルを開こうとしたときにファイルが存在しない場合、これは失敗します。ただし、上記のコードはファイルを書き込みモードで開いています(ファイルが存在しない場合は必ずしも失敗しません)。ディレクトリパスが存在し、呼び出しプロセスにそのディレクトリへの書き込み権限がある場合、ファイルが作成されます。

于 2013-03-08T23:56:37.973 に答える
2

fopen主に次の理由で失敗します。

  • ファイルが存在しません
  • ファイルのアクセス許可では、このファイルを開くことはできません(書き込み、読み取り、実行など)。
  • ファイルが別のプロセス(つまり、サードパーティのアプリケーション)によって使用されている
  • ファイルが別のPHPスクリプト/アセットによってロックされています
于 2013-03-08T23:37:21.700 に答える
1

fopen権限を取得していない場合やその他の低レベルのOSの問題がある場合は失敗する可能性があります。fopen複数回の書き込みは問題ありませんが、同時に書き込むと「ストライピング」が発生する可能性があるため、(ブロッキング)を使用してflockください。

于 2013-03-08T23:41:15.987 に答える