1. エラー:「トランザクション内で PDO インスタンスをスワップできません」
Laravel ソース コードをクエリすると、setPdo メソッドで例外がスローされたことが確認できます:
<?php public function setPdo($pdo) { if ($this->transactions >= 1) { throw new RuntimeException(" Can't swap PDO instance while within transaction. "); } $this->pdo = $pdo; return $this; } ?>
文字通りに理解すると、このエラーは When で発生します。トランザクションが有効になると、データベース接続が切り替わります。ただし、コード内でデータベース接続が明示的に切り替えられていない場合でも、このエラーが発生することがあります。たとえば、クエリ ステートメントの実行時にエラーが発生した場合、システムは tryAgainIfCausedByLostConnection メソッドを使用して、問題の原因が接続の喪失であるかどうかを判断します。その場合、システムは再接続時に reconnect メソッドを使用して再接続します。 setPdo メソッドが呼び出されるクリーンアップ作業を通じて一部の操作を実行します。
原因と結果を整理したら、問題を解決する方法が自然にわかります。ネットワークの状況を確認し、データベース接続が失われた理由を確認します。これは、特定のデバイスに問題がある可能性があります。特定のタイムアウトの設定が不適切なことが原因で発生します。比較的汚い解決策は、クエリを実行する前に DB::reconnect() メソッドを実行してデータベースに再接続することです。
2. エラー: "ジョブを削除できません: NOT_FOUND"
この問題は実際には Laravel とは関係なく、キュー サービス Beanstalk が原因で発生します。
この問題を解決するには、まずメッセージのライフサイクルを理解する必要があります。メッセージはキューに入れられると READY 状態になり、同時に TTR (実行時間) このメッセージが消費されると、消費時間が長すぎる場合、メッセージは削除されます。システム このコンシューマがハングアップしたものとみなされ、メッセージは RESERVED 状態から READY 状態に戻され、再処理のために別のコンシューマに渡されます。したがって、同じメッセージが複数のコンシューマによって処理される可能性があります。処理を完了した最初のコンシューマはメッセージを通常どおり削除できますが、残りのコンシューマはメッセージを削除するときに削除できないエラーを報告します。
解決策は非常に簡単です。まず、TTR 設定が小さすぎないようにする必要があります。次に、Beanstalk は、実行時間が長すぎる問題を解決するための特別なタッチ コマンドを提供します。同じメッセージが複数のコンシューマーによって同時に処理される状況を避けるために、ロックが必要になる場合があります。
3. エラー:「モデルのクエリ結果がありません」
Laravel の読み書き分離を有効にすると、コンシューマーはメッセージを処理するときに同様のエラーを受け取る可能性があります。潜在的に問題のあるキューコマンドはおそらく次のようになります:
<?php class Foo extends Command implements SelfHandling, ShouldBeQueued { use InteractsWithQueue, SerializesModels; protected $bar; public function __construct($id) { $this->bar = Bar::find($id); } public function handle() { // $this->bar } } ?>
明らかに、Laravel の読み取り/書き込み分離がオンになっていると、マスターとスレーブの遅延が原因で find は対応するデータをクエリできない可能性があります。これを分析すると、問題は解決します。書き込みメソッドは次のように変更される可能性が非常に高いです:
<?php class Foo extends Command implements SelfHandling, ShouldBeQueued { use InteractsWithQueue, SerializesModels; protected $bar; public function __construct($id) { $this->bar = Bar::onWriteConnection()->find($id); } public function handle() { // $this->bar } } ?>
つまり、クエリはLaravelのonWriteConnectionメソッドを通じてメインサーバー上で修正されますが、実際には無効です。問題の核心は、逆シリアル化中にシステムがサーバーから findOrFail を 1 回呼び出すことです。
<?php protected function getRestoredPropertyValue($value) { return $value instanceof ModelIdentifier ? (new $value->class)->findOrFail($value->id) : $value; } ?>
フレームワークにHACKできないので、onWriteConnectionは意味がありません。実際、問題を別の角度から見ると、シリアル化するときにデータベース オブジェクトを属性として使用しないように注意してください:
<?php class Foo extends Command implements SelfHandling, ShouldBeQueued { use InteractsWithQueue, SerializesModels; protected $id; public function __construct($id) { $this->id = $id; } public function handle() { $bar = Bar::onWriteConnection()->find($this->id); } } ?>
4. まとめ
上記は、Laravel を使用しているときに私が遭遇したいくつかの代表的なエラー レポートと解決策です。ご質問がございましたら、お気軽にお問い合わせください。この記事が皆さんの勉強や仕事に少しでもお役に立てれば幸いです。
Laravel の一般的なエラーと解決策をまとめたその他の関連記事については、PHP 中国語 Web サイトに注目してください。