Phalcon只更新改变的字段

前言

以前官网作了一次改版,运行一年多的时间,状态良好。在性能和抗压程度上都有了比较大的提高。php

然而,在对接了 TMS(第三方配送系统) 和电子发票以后,会常常发生订单状态异常的状况。html

问题

通过老大和慧哥的分析(我参与了问题的解决,未参与分析),流程以下:sql

  • 配送员在 TMS 操做订单完成(完成中);
  • 开电子发票的脚本获取了订单的信息;
  • TMS 更新完成,订单状态发生改变;
  • 开电子发票的脚本从新更新了订单的信息,订单被变动为 TMS 更新以前的状态。

正常的 Phalconupdate 流程以下:性能

$robot = Robots::findFirstById($id);
$robot->name = 'wali';
$robot->update();

// ------- or -------

$robot = Robots::findFirstById($id);
$robot->update(['name' => 'wali']);
复制代码

理想中的 SQL 语句:this

UPDATE `robots` SET `name` = 'wali' WHERE `id` = 1
复制代码

现实中的 SQL 语句:spa

UPDATE `robots` SET `name` = 'wali', `model` => '1' WHERE `id` = 1
复制代码

也就是说 Phalcon 会将取到的全部数据都更新一次。code

若是在A取到结果以后,B也操做并更新了这个记录以后,A再更新,那么B的操做就至关于没有作,这就形成了上面的尴尬一幕。htm

解决

解决方案有好几个,我会从最不建议的方式开始。blog

使用白名单

Phalcon 更新一条记录的过程当中,会调用 model 类中的 save 方法,而 save 方法提供了一个参数 whiteList,在 whiteList 以内的字段是不会被更新的。get

优势: 能够限制某些字段的更新。

缺点: 针对当前状况,须要在每一处操做限制,并且须要更改 update 的方式为 save,工做量太大。

本身写SQL

能够获取写服务以后,直接 execute SQL 语句,这样能够避免全部字段更新的状况。

优势: 适合批量更新或者多表更新的状况。

缺点: 和第一种方案同样,须要修改每一处地方,工做量大。

设置只更新变化的字段

Phalcon 自己仍是提供了只更新变化字段的方法的,调用也很简单,在 Model 初始化时,调用 useDynamicUpdate 方法,参数为 true

public function initialize() {
    $this->useDynamicUpdate(true); // 就是它,神奇的方法
    $this->setReadConnectionService('slave');
    $this->setWriteConnectionService('master');
    $this->setSource($this->_tableName);
}
复制代码

优势: 便捷,快速,改动地方少。

缺点: 固然是有的,不过我没有想到...

总结

有些雷,会在不知不觉中埋下,因此对于未知的东西,仍是要多了解,才可以做出更加正确的决定。

-- EOF --

本文转载自IMJCW

原文连接:Phalcon只更新改变的字段