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);
}
}
?>
猜你喜欢
- date() 获取日期,格式:2004-2-28 time() 获取时间,格式:22:24:59 now() 获取日期和时间 格式: 200
- 我们都知道 vue 中可以使用 modal 来实现 input 内容数据的双向绑定。小程序好像没有提供相应的方法支持,就需要我们自己写了。原
- 如何对设计进行评判,一定有很多答案,有利有弊。问100位设计师,会得到100种回答。用线上PV、UV等数据说话,更多受产品属性、运营动作影响
- 教育信息化时代,考试成绩也要求上网公布。一次我将考试成绩制作成一个HTML文件,如图1所示,领导审查的意见是“将成绩按名次排列”,可是所有的
- 不用切图,只要设置基本的 图片及其属性即可!用鼠标右键控制图片翻转!<style>*{ FONT-SIZE: 12px; }se
- ASP链接MSSQL2005的链接字符串如下:Provider=SQLNCLI;Server=.\SQLEXPRESS;Database=m
- 在HTML中,我们设置border=”1″ 时,表格边框实际大小是2px,那如果我们要做成1px的细线表格要怎么办?以前在做1px的表格的时
- 1、HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Applicatio
- php对数字进行万。亿的转化/** * 格式化数字 */public function float_number($number){ &nb
- 相信很多与页面打过交道的同学都对 Yahoo 的 Best Practices for Speeding Up Your Web Site
- 什么是RC4算法呢?也许您还不知道,没关系我为您找了下相关资料方便大家查看;RC4加密算法 RC4加密算法是大名鼎鼎的RSA三人组
- 这篇论坛文章(赛迪网技术社区)主要介绍了MySQL数据库主从复制的相关概念及设置方法,详细内容请大家参考下文:MySQL支持单向、异步复制,
- asp程序出错后,错误提示不是很清楚明白,让人摸不着头脑,用下面方法看看有没有帮助(此法目前只适合除ADO错误外的错误) &nb
- 停止mysql服务(以管理员身份,在cmd命令行下运行) net stop mysql或者在服务中停止mysql服务。使用 mysqld –
- 代码如下:declare @cmd nvarchar(4000) set @cmd = N'exec [?].sys.sp_chan
- 一、Browser Capabilities组件 该组件最主要的作用是:提取识别客户端浏览器的版本信息。其原理是这样的:当客户端浏览器向服务
- 本文实例讲述了Python类的用法。分享给大家供大家参考。具体如下:先看一段代码:#!/usr/bin/env pythonclass Te
- 废话不多说了,直接给大家贴代码了,具体代码如下所示:// ----ajax begin $.ajax({type: "
- 本文实例讲述了PHP依赖注入原理与用法。分享给大家供大家参考,具体如下:引言依然是来自到喜啦的一道面试题,你知道什么是依赖注入吗?依赖注入(
- 作者:Roland Smart原文链接:http://www.adaptivepath.com/ideas/newsletter/archi