Phalcon只更新改變的欄位
阿新 • • 發佈:2019-02-11
前言
之前官網做了一次改版,執行一年多的時間,狀態良好。在效能和抗壓程度上都有了比較大的提升。
然而,在對接了 TMS(第三方配送系統)
和電子發票之後,會經常發生訂單狀態異常的情況。
問題
經過老大和慧哥的分析(我參與了問題的解決,未參與分析),流程如下:
- 配送員在
TMS
操作訂單完成(完成中); - 開電子發票的指令碼獲取了訂單的資訊;
TMS
更新完成,訂單狀態發生改變;- 開電子發票的指令碼重新更新了訂單的資訊,訂單被變更為
TMS
更新之前的狀態。
正常的 Phalcon
的 update
流程如下:
$robot = Robots::findFirstById($id );
$robot->name = 'wali';
$robot->update();
// ------- or -------
$robot = Robots::findFirstById($id);
$robot->update(['name' => 'wali']);
理想中的 SQL
語句:
UPDATE `robots` SET `name` = 'wali' WHERE `id` = 1
現實中的 SQL
語句:
UPDATE `robots` SET `name` = 'wali', `model` => '1' WHERE `id` = 1
也就是說 Phalcon
會將取到的所有資料都更新一次。
如果在A取到結果之後,B也操作並更新了這個記錄之後,A再更新,那麼B的操作就相當於沒有做,這就造成了上面的尷尬一幕。
解決
解決方案有好幾個,我會從最不建議的方式開始。
使用白名單
Phalcon
更新一條記錄的過程中,會呼叫 model
類中的 save
方法,而 save
方法提供了一個引數 whiteList
,在 whiteList
之內的欄位是不會被更新的。
優點:可以限制某些欄位的更新。
缺點:針對當前情況,需要在每一處操作限制,而且需要更改 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);
}
優點:便捷,快速,改動地方少。
缺點:當然是有的,不過我沒有想到…
總結
有些雷,會在不知不覺中埋下,所以對於未知的東西,還是要多瞭解,才能夠作出更加正確的決定。