最近公司後端項目進行了改造升級,由以前的laravel5.6版本升級到了laravel5.8版本,升級後系統產生了很多SQL執行錯誤,可是在老版本系統運行的好好的,因而就產生了今日的扒坑之旅。php
老系統(linux + laravel5.6 + php7.2 + mysql5.7)mysql
升級後新系統(linux +laravel5.8 + php7.2 + mysql5.7)linux
只單純升級了laravel框架版本,並沒有升級其餘相關服務依賴.laravel
可是卻出現大量的SQL執行錯誤,異常監控以下:sql
致使這段服務出錯的是這樣的一段業務邏輯,下面經過一段demo來模擬.後端
$pivot = UserRole::firstOrCreate([ 'user_id' => 3, 'role_id' => 3, ]); $this->addRoleHistory($user,$pivot->id); dd($pivot->id);
在laravel5.6版本中這段代碼運行起來毫無問題,但升級到5.8版本中就會引起大量的SQL執行錯誤,就像下面這樣.php7
laravel5.6: dd($pivot->id); //10002 laravel5.8: dd($pivot->id); //null
在5.6中保存中的數據還能正常獲取到ID,在5.8中怎麼就不行了呢,因而立刻去查看了laravel5.8的發行說明,也沒有發現對Pivot模型取消獲取自增ID的改動,因而開始進行5.8源碼查閱。。。框架
首先對5.6和5.8的firstOrCreate函數進行了對比,發現無改動,代碼邏輯執行無誤。函數
而後繼續翻閱model->save()函數的代碼
,發現不存在的數據是經過insertAndSetId該函數插入數據並設置主鍵ID
測試
但insertAndSetId函數又是經過incrementing這樣的一個成員屬性來控制的,屬性的默認值是true
當這個屬性變動時就不會執行者一步驟,難道這個成員屬性在被操做過了?
因而立馬查看了5.8的pivot模型源碼.
最終發現是5.8的在中間表Pivot Class默認將incrementing設置成了false,因此數據被成功插入,可是沒有設置插入後的主鍵ID,形成剩餘服務崩潰,沒能正常運行...
在每一個Pivot Class中從新覆蓋掉incrementing屬性值爲true便可.
class UserRole extends Pivot { public $incrementing = true; protected $fillable = [ 'user_id', 'role_id', ]; }
修復後:
laravel5.8: dd($pivot->id); //10003
因而又去仔細看了一遍laravel5.7~laravel5.8發行說明,發現依然沒有提到這個改動的緣由,因而又去google了一遍,依然沒有找到這個梗的緣由所在.
最後仍是成功修復掉了該處改動帶來的問題,也提醒了咱們在後續版本升級時仍是須要多注重UT的覆蓋及版本兼容改動測試,多個維度來保證項目質量。
laravel5.7發行說明 :https://laravel.com/docs/5.7/...
laravel5.8發行說明 :https://laravel.com/docs/5.8/...