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 相关文章推荐
js对象内部访问this修饰的成员函数示例
Apr 27 Javascript
JavaScript中的call方法和apply方法使用对比
Aug 12 Javascript
JavaScript实现使用Canvas绘制图形的基本教程
Oct 27 Javascript
AngularJS中transclude用法详解
Nov 03 Javascript
基于vuejs+webpack的日期选择插件
May 21 Javascript
bootstrap学习使用(导航条、下拉菜单、轮播、栅格布局等)
Dec 01 Javascript
vuejs响应用户事件(如点击事件)
Mar 14 Javascript
微信小程序 websocket 实现SpringMVC+Spring+Mybatis
Aug 04 Javascript
vue cli使用绝对路径引用图片问题的解决
Dec 06 Javascript
javascript触发模拟鼠标点击事件
Jun 26 Javascript
解析vue、angular深度作用选择器
Sep 11 Javascript
jQuery实现点击滚动到指定元素上的方法分析
Mar 19 jQuery
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
SONY SRF-22W(33W)的电路分析和维修案例
2021/03/02 无线电
3款值得推荐的微信开发开源框架
2014/10/28 PHP
php版微信公众平台回复中文出现乱码问题的解决方法
2016/09/22 PHP
PHP多维数组指定多字段排序的示例代码
2018/05/16 PHP
php处理多图上传压缩代码功能
2018/06/13 PHP
JavaScript 空位补零实现代码
2010/02/26 Javascript
angular.js分页代码的实例
2016/07/27 Javascript
nodejs中向HTTP响应传送进程的输出
2017/03/19 NodeJs
vue.js todolist实现代码
2017/10/29 Javascript
使用npm安装最新版本nodejs
2018/01/18 NodeJs
vue2.0组件之间传值、通信的多种方式(干货)
2018/02/10 Javascript
Node.js的进程管理的深入理解
2019/01/09 Javascript
jquery.pager.js分页实现详解
2019/07/29 jQuery
js的新生代垃圾回收知识点总结
2019/08/22 Javascript
node.js使用zlib模块进行数据压缩和解压操作示例
2020/02/12 Javascript
[01:07]2015国际邀请赛 中国区预选赛精彩回顾
2015/06/15 DOTA
python遍历文件夹并删除特定格式文件的示例
2014/03/05 Python
Python中几种操作字符串的方法的介绍
2015/04/09 Python
Python 探针的实现原理
2016/04/23 Python
Python2和Python3中urllib库中urlencode的使用注意事项
2018/11/26 Python
selenium+python自动化测试之鼠标和键盘事件
2019/01/23 Python
python 列表中[ ]中冒号‘:’的作用
2019/04/30 Python
python中时间模块的基本使用教程
2019/05/14 Python
python读写配置文件操作示例
2019/07/03 Python
Python2与Python3的区别点整理
2019/12/12 Python
Python集成开发工具Pycharm的安装和使用详解
2020/03/18 Python
移动web模拟客户端实现多方框输入密码效果【附代码】
2016/03/25 HTML / CSS
ONLY瑞典官网:世界知名服装品牌
2018/06/19 全球购物
世界上最大的乐谱选择:Sheet Music Plus
2020/01/18 全球购物
美国床垫连锁店:Mattress Firm
2021/02/13 全球购物
装潢设计实习自我鉴定
2013/09/19 职场文书
党员干部公开承诺书
2014/03/26 职场文书
标准的毕业生自荐信
2014/04/20 职场文书
优秀学生党员先进事迹材料
2014/05/29 职场文书
2016寒假社会实践心得体会范文
2015/10/09 职场文书
创业计划书之酒厂
2019/10/14 职场文书