0

Web サービスにRecess フレームワークを使用しています。その一環として、SQLite データベースとして提供される Recess のキャッシュ メカニズムを使用しています。

私たちは、このキャッシング メカニズムを約 1 年間、快適に使用しています。ただし、SQLite データベースが「ロック」されて問題が発生するという問題が 3 回発生しました。表示されるメッセージは、「例外 'PDOException' とメッセージ 'SQLSTATE[HY000]: 一般エラー: 5 データベースがロックされています...」です。

私は周りを検索しましたが、それは一般的な問題のようであり、その可能性を最小限に抑える方法や防止する方法について多くの議論があります (たとえば、drupal ボード)。ただし、私の問題はこれとは少し異なるようです。2 つの PHP プロセスがまったく同時に SQLite データベースにアクセスしようとすると、そのうちの 1 つでロック エラーが発生します。このような状況では、問題を最小限に抑える努力が理にかなっています。しかし、私のアプリケーションでは、問題が発生し始めると (おそらく同時実行が原因で)、SQLite データベースはその時点から永久にロックされます。この時点以降のすべてのキャッシュ アクセス リクエストは、PDOException を取得します。私たちの解決策はキャッシュ ファイルを削除することでした。これは世界の終わりではありませんが、これには手動での介入が必要であり、構築されたキャッシュ データが失われることを意味します。

なぜこれが起こるのでしょうか?そもそもロックを取得する理由は他にありますか? ロックが持続するのはなぜですか?プログラムでクリアする方法はありますか?そもそもそれを防ぐ方法はありますか?

私がこれまでに検討している2つの「解決策」は次のとおりです。

  1. キャッシュ アクセス関数の周りに try-catch を配置します。例外が発生した場合は、キャッシュを無視してテクニカル サポートに連絡し、手動でキャッシュをクリアしてください。
  2. SQLite ファイルにミューテックス ( PHP flockを使用) を使用して、同時実行性の問題を回避します (ただし、これが根本的な原因であるとは確信していません)。

情報や提案をいただければ幸いです。

4

1 に答える 1

1

良い...

  1. 技術サポートが存在しない問題を処理できるようにします。
  2. SQLite が独自のロックを行うという事実を無視します。(SQLite3 はそれを最適化しました!)

私のオタクをドアに立てたままにして、「解決策」番号3(リストに記載されていません)を使用し、キャッシュアクセス関数の周りにtry-catchを配置するだけです。例外が発生した場合は、短いスリープを実行してから、例外を発生させた関数を再度呼び出します。

thisFunction(...) 
{
    ....
    try
    {
      ....
    }
    catch(Exception $e)
    {
      sleep(rand(1,3))
      thisFunction(...);
    }
    ....
}

そうすれば、実際に sqlite が助けようとしているエラーから何かを得ることができます。;)

于 2011-12-12T09:35:12.170 に答える