Laravel中常见的错误与解决方法小结


Posted in Javascript onAugust 30, 2016

一、报错: 「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 导致的。

Laravel中常见的错误与解决方法小结
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);
  }
}

?>

四、总结

以上就是我在使用Laravel遇到的几个有代表性的报错以及解决方案,如果有问题欢迎大家一起交流。希望这篇文章对大家的学习或者工作能带来一定的帮助。

Javascript 相关文章推荐
JavaScript 直接操作本地文件的实现代码
Dec 01 Javascript
jquery 插件学习(一)
Aug 06 Javascript
特殊情况下如何获取span里面的值
May 20 Javascript
最精简的JavaScript实现鼠标拖动效果的方法
May 11 Javascript
jQuery Real Person验证码插件防止表单自动提交
Nov 06 Javascript
VUE使用vuex解决模块间传值问题的方法
Jun 01 Javascript
Angularjs过滤器实现动态搜索与排序功能示例
Dec 13 Javascript
详解微信小程序-扫一扫 wx.scanCode() 扫码大变身
Apr 30 Javascript
JS前端知识点总结之页面加载事件,数组操作,DOM节点操作,循环和分支
Jul 04 Javascript
解决Vue中的生命周期beforeDestory不触发的问题
Jul 21 Javascript
微信小程序实现自定义底部导航
Nov 18 Javascript
微信小程序组件生命周期的踩坑记录
Mar 03 Javascript
js中常用的Tab切换效果(推荐)
Aug 30 #Javascript
基于cssSlidy.js插件实现响应式手机图片轮播效果
Aug 30 #Javascript
JavaScript探测CSS动画是否已经完成的方法
Aug 30 #Javascript
基于JavaScript实现鼠标箭头移动图片跟着移动
Aug 30 #Javascript
很棒的js Tab选项卡切换效果
Aug 30 #Javascript
js改变透明度实现轮播图的算法
Aug 24 #Javascript
标准的js无缝滚动效果
Aug 30 #Javascript
You might like
PHP+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
2007/02/15 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
多广告投放代码 推荐
2006/11/13 Javascript
ASP中Sub和Function的区别说明
2020/08/30 Javascript
jquery入门—访问DOM对象方法
2013/01/07 Javascript
JQuery筛选器全系列介绍
2013/08/27 Javascript
javascript常用的设计模式
2017/02/09 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
微信小程序封装http访问网络库实例代码
2017/05/24 Javascript
javascript+html5+css3自定义弹出窗口效果
2017/10/26 Javascript
Vue组件创建和传值的方法
2018/08/17 Javascript
Node.js原生api搭建web服务器的方法步骤
2019/02/15 Javascript
使用JQuery自动完成插件Auto Complete详解
2019/06/18 jQuery
微信小程序下拉框搜索功能的实现方法
2019/07/31 Javascript
mpvue微信小程序的接口请求fly全局拦截代码实例
2019/11/13 Javascript
JavaScript复制变量三种方法实例详解
2020/01/09 Javascript
使用konva和vue-konva库实现拖拽滑块验证功能
2020/04/27 Javascript
微信小程序picker组件两列关联使用方式
2020/10/27 Javascript
Python代理抓取并验证使用多线程实现
2013/05/03 Python
python实现从网络下载文件并获得文件大小及类型的方法
2015/04/28 Python
python实现基于SVM手写数字识别功能
2020/05/27 Python
Python中 Global和Nonlocal的用法详解
2020/01/20 Python
Python脚本破解压缩文件口令实例教程(zipfile)
2020/06/14 Python
Python实现钉钉/企业微信自动打卡的示例代码
2021/02/02 Python
html5新增的定时器requestAnimationFrame实现进度条功能
2018/12/13 HTML / CSS
日本快乐生活方式购物网站:Shop Japan
2018/07/17 全球购物
在线课程:Skillshare
2019/04/02 全球购物
如何通过 CSS 写出火焰效果
2021/03/24 HTML / CSS
上课看小说检讨书
2014/02/22 职场文书
2014年社区庆元旦活动方案
2014/03/08 职场文书
村主任个人对照检查材料
2014/10/01 职场文书
房屋租房协议书范本
2014/12/04 职场文书
三峡大坝导游词
2015/01/31 职场文书
慰问信(范文3篇)
2019/10/23 职场文书
Spring Data JPA框架Repository自定义实现
2022/04/28 Java/Android
腾讯云服务器部署前后分离项目之前端部署
2022/06/28 Servers