1. Report an error: "Can't swap PDO instance while within transaction"
By querying the Laravel source code, you can confirm that the exception is thrown in setPdo method:
<?phppublic function setPdo($pdo){ if ($this->transactions >= 1) { throw new RuntimeException(" Can't swap PDO instance while within transaction. "); } $this->pdo = $pdo; return $this;}?> Literally, this error occurs because the database connection is switched when the transaction is turned on. However, sometimes, this error may occur even if the code does not explicitly switch database connections. 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 cleaning work through the disconnect method, and setPdo method is called.
After clarifying the causes and consequences, you will naturally know how to solve the problem: check the network situation and confirm the cause of the database connection loss. This may be because there is a problem with a certain device, or it may be because of improper timeout settings. A relatively dirty method is to execute DB::reconnect() method before querying and reconnecting to the database.
2. Error: "Cannot delete job: NOT_FOUND"
This problem actually has nothing to do with Laravel, but is caused by the queue service Beanstalk.
Beanstalk
To solve this problem, you need to first understand the life cycle of a message: when a message is placed in the queue, it enters the READY state, and at the same time, it will associate a TTR(time to run) timer to indicate the time the 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 is too long, longer than TTR , the system will think that the consumer has hung up, and then return the message from RESERVED state to READY state and hand it over to another consumer for reprocessing. Therefore, the same message may be processed by multiple consumers. The first consumer who has processed it can delete the message normally, while the other consumers will report an error that cannot be deleted when deleting the message.
The solution is very simple. First, you need to ensure that TTR setting cannot be too small; second, 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. Report an error: "No query results for model"
When Laravel read and write separation is activated, a consumer may receive a similar error when processing messages. A queue command with potential problems is roughly as follows:
<?phpclass 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 }}?> It is obvious that when Laravel read and write separation is turned on, because of the master-slave delay, find may not be able to query the corresponding data. Once we have analyzed it here, it is likely that the writing method will be modified to the following:
<?phpclass 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 }}?> That is to say, the query is pinned to the main server through Laravel's onWriteConnection method, but it is actually invalid. The crux of the problem is that when deserialization, the system will call findOrFail from the server.
<?phpprotected function getRestoredPropertyValue($value){ return $value instanceof ModelIdentifier ? (new $value->class)->findOrFail($value->id) : $value;}?> Because we can't HACK into the framework, onWriteConnection makes no sense. In fact, look at the problem from a different perspective. As long as you are serialized, make sure not to use database objects as attributes:
<?phpclass 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 several representative error reports and solutions I encountered when using Laravel. If you have any questions, please feel free to communicate with each other. I hope this article will be of some help to everyone's study or work.