1. Error: "Can't swap PDO instance while within transaction"
By querying the Laravel source code, you can confirm that the exception was thrown in the setPdo method:
<?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; } ?>
Press Literally understood, this error occurs because the database connection is switched while the transaction is enabled. However, sometimes, this error may occur even if the database connection is not explicitly switched in the code. For example, when an error occurs when executing a query statement, the system will use the tryAgainIfCausedByLostConnection method to determine whether the problem is caused by a lost connection. If so, the system will reconnect through the reconnect method. When reconnecting, the system will perform some operations through the disconnect method. Cleanup work, in which the setPdo method is called.
After sorting out the cause and effect, you will naturally know how to solve the problem: check the network situation and confirm the reason why the database connection is lost. This may be a problem with a certain device, or it may be an improper setting of a timeout Caused by. A relatively dirty solution is to execute the DB::reconnect() method to reconnect to the database before querying.
2. Error: "Cannot delete job: NOT_FOUND"
This problem actually has nothing to do with Laravel, but is caused by the queue service Beanstalk.
To solve this problem, you need to first understand the life cycle of a message: when a message is put into the queue, it enters the READY state. At the same time, It will be associated with a TTR (time to run) timer, indicating the time this message is allowed to run. When this message is consumed, it enters the RESERVED state. After consumption, the message will be deleted. If the consumption time If it is too long, longer than TTR, then the system will consider that the consumer has hung up, and will return the message from the RESERVED state to the READY state, and hand it over to another consumer for reprocessing. Therefore, the same message may be processed by multiple consumers. The first consumer to complete the processing can delete the message normally, while the remaining consumers will report an error that cannot be deleted when deleting the message.
The solution is very simple. First, you need to ensure that the setting of TTR cannot be too small; secondly, Beanstalk actually provides a special touch command to solve the problem of too long execution time. In addition, sometimes, We may need to lock at the application level to avoid the situation where the same message is processed by multiple consumers at the same time.
3. Error: "No query results for model"
Under the premise of activating Laravel's read-write separation, consumers may receive similar errors when processing messages. A potentially problematic queue command probably looks like this:
<?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 } } ?>
Obviously, when Laravel read-write separation is turned on, find may not be able to query the corresponding data due to master-slave delay. After our analysis has reached this point, it is likely that the writing method will be modified as follows:
<?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 } } ?>
In other words, the query is fixed on the main server through Laravel's onWriteConnection method, but it is actually invalid. The crux of the problem is that during deserialization, the system will call findOrFail once from the server.
<?php protected function getRestoredPropertyValue($value) { return $value instanceof ModelIdentifier ? (new $value->class)->findOrFail($value->id) : $value; } ?>
Because we cannot HACK into the framework, onWriteConnection is meaningless. In fact, looking at the problem from another angle, just make sure not to use database objects as attributes when serializing:
<?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. Summary
The above are a few things I encountered when using Laravel Representative error reports and solutions. If you have any questions, you are welcome to share them. I hope this article can be of some help to everyone's study or work.
For more related articles on common errors and solutions in Laravel, please pay attention to the PHP Chinese website!