以前項目中,項目組計劃將現場的MySQL5.5升級到5.7,以提高主從同步性能、使用半同步複製,以及解決一些現場問題等。安排測試組進行驗證,測試同事反饋實驗室環境中發現有入庫失敗,我查看了error_log日誌,發現有很多以下報錯。mysql
[Err] 1364 - Field `xx_field` doesn't have a default value
業務版本先後都是同樣的,好端端的mysql怎麼忽然就部分表寫入失敗呢?根據上面的日誌很快猜到是 sql_mode 問題: NOT NULL 列沒有默認值但代碼裏也沒給值,在非嚴格模式下,int列默認爲0,string列默認爲''了,因此不成問題;但在嚴格模式下,是直接返回失敗的。sql
那麼看看吧,果真如此。數據庫
mysql> show variables like "sql_mode"; +---------------+--------------------------------------------+ | Variable_name | Value | +---------------+--------------------------------------------+ | sql_mode | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | +---------------+--------------------------------------------+
但測試同事反饋並無更改過該參數。查閱資料,發現:MySQL5.6.6 之後版本默認就是NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,5.5默認爲 '' 。session
嚴格模式是合理的,更能保證系統的健壯性,因此解決方案並非set global variables去除STRICT_TRANS_TABLES,而是業務側修改完善,加上默認值。性能
凡事講究觸類旁通,PDCA。測試
嚴格模式,進行數據的嚴格校驗,錯誤數據不能插入,報error錯誤。 spa
單獨指 INSERT、UPDATE出現少值或無效值該如何處理: 日誌
1. sql_mode='ANSI'code
ANSI模式:寬鬆模式,對插入數據進行校驗,若是不符合定義類型或長度,對數據類型調整或截斷保存,報warning警告。blog
更改語法和行爲,使其更符合標準SQL,至關於REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE。
2.sql_mode='TRADITIONAL'
TRADITIONAL 模式:嚴格模式,當向mysql數據庫插入數據時,進行數據的嚴格校驗,保證錯誤數據不能插入,報error錯誤。用於事物時,會進行事物的回滾。
更像傳統SQL數據庫系統,該模式的簡單描述是當在列中插入不正確的值時「給出錯誤而不是警告」。
至關於 STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION。
set session sql_mode = 'no_auto_create_user';
MySQL5.7及以前版本可設置,MySQL8以後爲默認設置,先create user才能grant。
set session sql_mode = 'no_zero_in_date';
set session sql_mode = 'no_zero_date';
no_zero_date認爲日期 '0000-00-00' 非法,與是否設置後面的嚴格模式有關。
set session sql_mode = 'no_engine_substitution';
使用 ALTER TABLE或CREATE TABLE 指定 ENGINE 時, 須要的存儲引擎被禁用或未編譯,該如何處理。
啓用NO_ENGINE_SUBSTITUTION時,此時直接拋出錯誤;
不設置此值時,CREATE用默認的存儲引擎替代,ATLER不進行更改,並拋出一個 warning。