1. Fehler: „PDO-Instanz kann während der Transaktion nicht ausgetauscht werden“
Durch Abfrage des Laravel-Quellcodes können Sie bestätigen, dass die Ausnahme in der setPdo-Methode ausgelöst wurde:
<?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; } ?>
Im wahrsten Sinne des Wortes tritt dieser Fehler auf, weil die Datenbankverbindung umgeschaltet wird, während die Transaktion aktiviert ist. Manchmal kann dieser Fehler jedoch auch dann auftreten, wenn die Datenbankverbindung im Code nicht explizit umgeschaltet wird. Wenn beispielsweise beim Ausführen einer Abfrageanweisung ein Fehler auftritt, ermittelt das System mithilfe der Methode tryAgainIfCausedByLostConnection, ob das Problem durch eine verlorene Verbindung verursacht wurde. Wenn dies der Fall ist, stellt das System die Verbindung wieder her Führen Sie einige Vorgänge über die Disconnect-Methode aus, bei der die setPdo-Methode aufgerufen wird.
Nachdem Sie die Ursache und Wirkung geklärt haben, wissen Sie natürlich, wie Sie das Problem lösen können: Überprüfen Sie die Netzwerksituation und bestätigen Sie den Grund, warum die Datenbankverbindung unterbrochen wird. Dies kann ein Problem mit einem bestimmten sein Gerät, oder es liegt möglicherweise eine falsche Einstellung eines Timeouts vor. Eine relativ schmutzige Lösung besteht darin, vor der Abfrage die Methode DB::reconnect() auszuführen, um die Verbindung zur Datenbank wiederherzustellen.
2. Fehler: „Kann Job nicht löschen: NOT_FOUND“
Dieses Problem hat eigentlich nichts mit Laravel zu tun, sondern wird durch den Warteschlangendienst Beanstalk verursacht.
Um dieses Problem zu lösen, müssen Sie zunächst den Lebenszyklus einer Nachricht verstehen: Wenn eine Nachricht in die Warteschlange gestellt wird, wechselt sie gleichzeitig in den Status BEREIT Zeit, Es wird mit einem TTR-Timer (Time to Run) verknüpft, der die Zeit angibt, die diese Nachricht ausführen darf. Wenn diese Nachricht verbraucht ist, wechselt sie in den Status RESERVIERT Zeit Wenn sie zu lang ist, länger als TTR, geht das System davon aus, dass der Verbraucher aufgelegt hat, versetzt die Nachricht vom Status RESERVIERT in den Status BEREIT und übergibt sie zur erneuten Verarbeitung an einen anderen Verbraucher. Daher kann dieselbe Nachricht von mehreren Verbrauchern verarbeitet werden. Der erste Verbraucher, der die Verarbeitung abschließt, kann die Nachricht normal löschen, während die übrigen Verbraucher beim Löschen der Nachricht einen Fehler melden, der nicht gelöscht werden kann.
Die Lösung ist sehr einfach. Erstens müssen Sie sicherstellen, dass die TTR-Einstellung nicht zu klein sein darf. Zweitens bietet Beanstalk tatsächlich einen speziellen Touch-Befehl, um das Problem einer zu langen Ausführungszeit zu lösen Darüber hinaus müssen wir manchmal eine Sperre auf Anwendungsebene durchführen, um zu vermeiden, dass dieselbe Nachricht von mehreren Verbrauchern gleichzeitig verarbeitet wird.
3. Fehler: „Keine Abfrageergebnisse für Modell“
Wenn die Lese-/Schreibtrennung von Laravel aktiviert ist, erhalten Verbraucher möglicherweise ähnliche Fehler bei der Verarbeitung von Nachrichten. Ein potenziell problematischer Warteschlangenbefehl sieht wahrscheinlich so aus:
<?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 } } ?>
Wenn die Lese-/Schreibtrennung von Laravel aktiviert ist, kann find aufgrund der Master-Slave-Verzögerung möglicherweise nicht einmal die entsprechenden Daten abfragen Wenn wir dies analysieren, werden wir die Schreibweise wahrscheinlich wie folgt ändern:
<?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 } } ?>
Mit anderen Worten, die Abfrage wird auf dem Hauptserver durch die onWriteConnection-Methode von Laravel behoben, ist aber tatsächlich ungültig. Der Kern des Problems besteht darin, dass das System während der Deserialisierung einmal findOrFail vom Server aufruft.
<?php protected function getRestoredPropertyValue($value) { return $value instanceof ModelIdentifier ? (new $value->class)->findOrFail($value->id) : $value; } ?>
Da wir uns nicht in das Framework hacken können, ist onWriteConnection bedeutungslos. Wenn Sie das Problem aus einem anderen Blickwinkel betrachten, stellen Sie einfach sicher, dass Sie bei der Serialisierung keine Datenbankobjekte als Attribute verwenden:
<?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. Zusammenfassung
Das Obige ist das, was mir bei der Verwendung begegnet ist Laravel Mehrere repräsentative Fehlerberichte und Lösungen. Wenn Sie Fragen haben, teilen Sie diese bitte mit. Ich hoffe, dass dieser Artikel für jedermann beim Lernen oder bei der Arbeit hilfreich sein kann.
Weitere verwandte Artikel zu häufigen Fehlern und Lösungen in Laravel finden Sie auf der chinesischen PHP-Website!