Laravel中常见的错误与解决方法小结
作者:daisy 发布时间:2023-09-09 19:38:37
一、报错: 「Can't swap PDO instance while within transaction」
通过查询 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;
}
?>
按字面意思理解,出现此错误是因为在开启了事务的情况下,切换了数据库连接。不过有时候,即便代码里没有显式的切换数据库连接,也有可能出现此错误。比如说在执行查询语句出错的时候,系统会通过 tryAgainIfCausedByLostConnection
方法判断问题是不是因为丢失连接导致的,如果是,那么系统会通过 reconnect
方法重新连接,在重新连接的时候,系统会通过 disconnect
方法执行一些清理工作,其中调用了 setPdo
方法。
理清了前因后果,自然就知道如何解决问题了:检查网络情况,确认数据库连接丢失的原因,这可能是某个设备有问题,也可能是某个 timeout
设置不当所致。一个相对 dirty
的处理方法是在查询前执行一下 DB::reconnect()
方法重新连接一下数据库。
二、报错:「Cannot delete job: NOT_FOUND」
此问题实际上和 Laravel 没太大关系,而是队列服务 Beanstalk 导致的。
Beanstalk
要解决这个问题,需要先理解一个消息的生命周期:当一个消息被放入队列的时候,它就进入了 READY
状态,与此同时,它会关联一个 TTR(time to run)
计时器,表示此消息允许运行的时间,当此消息被消费时,它就进入了 RESERVED
状态,消费完后,此消息就会被删除,如果消费的时间过长,比 TTR
还长,那么系统会认为认为此消费者已经挂了,进而会把消息从 RESERVED
状态退回到 READY
状态,交给另一个消费者重新处理。于是乎同一个消息可能会被多个消费者处理,第一个处理完的消费者可以正常的删除消息,而其余的消费者在删除消息的时候就会报无法删除的错误。
解决方法很简单,首先,需要确保 TTR
的设置不能太小;其次,实际上 Beanstalk
提供了一个专门的 touch
命令来解决执行时间过长的问题,此外,有些时候我们可能需要在应用层面上通过加锁来规避同一个消息被多个消费者同时处理的情况。
三、报错:「No query results for model」
在激活了 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
调用。
<?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);
}
}
?>


猜你喜欢
- pyecharts显示数据为百分比的柱状图pyecharts是做数据分析的好帮手,柱状图比较简单,网站例子不够多,一般柱状图就是直接传两组数
- 目录前言1. 效果图2. 原理3. 源码3.1 Numpy实现傅里叶变换3.2 OpenCV实现傅里叶变换3.3 HPF or LPF?参考
- pyyaml模块在python中用于处理yaml格式数据,主要使用yaml.safe_dump()、yaml.safe_load()函数将p
- 学生信息系统提示:python编写的学生成绩管理系统,包括8个功能和打包教程一、功能界面 def menum():
- 问题在使用matplotlib作图的时候,有的时候会遇到画图时坐标轴重叠,显示不全和图片保存时不完整的问题。如下:解决方案画图时重叠或者显示
- 如果index是时间序列就不用转datetime;但是如果时间序列是表中的某一列,可以把这一列设为index例如:代码:DF=df2.set
- 1,使用到的第三方库requestsBeautifulSoup 美味汤worldcloud 词云jieba 中文分词matplotlib 绘
- 适配器模式说明说明: 适配器模式,一般是为要使用的接口,不符本应用或本系统使用,而需引入的中间适配层类或对象的情况;场景: 就好比我们买了台
- ASP开发中有用的函数(function)集合,挺有用的,请大家保留!'******************************
- 看代码吧~package mainimport ( "fmt")type XCDataStu struct { Id &
- python配置matlab库1、确认配置版本matlab与python有相互对应的版本,需要两者版本兼容。如不兼容,需要调整matlab版
- 前言Django提供了多种装饰器, 其中login_required可能是经常会使用到的。 这里介绍下四种使用此装饰器的办法。当然, 在使用
- 一、mysql主(称master)从(称slave)复制的原理: (1).mas
- 前言python数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间。下面话不多说,来看看详细的介绍吧
- 我就废话不多说了,大家还是直接看代码吧~package main import "os" func main () {
- 同样,对事务日志进行备份也只会截断不活动事务的那部分事务日志,所以打开的事务会导致日志变多(甚至达到物理限制),直到事务被提交或回滚。要找到
- 上一篇我们讲过Cookie相关的知识,了解到Cookie是为了交互式web而诞生的,它主要用于以下三个方面:会话状态管理(如用户登录状态、购
- 简介rpc:远程过程调用协议。简单的来说就是客户端可以很方便得远程调用服务端的接口程序,而不用管底层是如何实现的。XML-RPC的全称是XM
- cmp()方法返回两个数的差的符号: -1 如果 x < y, 0 如果 x == y, 或者 1 如果 x > y
- 先来一个官网链接:https://www.xmind.cn/有钱的也可以支持一波然后开始吧–百度网盘获取地址:链接: h