首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 嚴格模式啟用指南:為什麼生產環境必須開啟?

     編輯:MySQL 資料庫相關知識

什麼是嚴格模式?

MySQL 預設運行在「寬鬆模式」:數據截斷只警告、非法日期存 '0000-00-00'、字符串塞進整型欄位自動轉 0、**不報錯、不中斷、悄悄存下髒數據**。嚴格模式 (STRICT_TRANS_TABLES / STRICT_ALL_TABLES) 則在 INSERT/UPDATE 遇到數據不合法時**直接報錯回滾**,在源頭攔截髒數據。

為什麼開發/測試/生產環境都必須開啟?

  1. 早發現 Bug:代碼邏輯錯誤 (如長度超限、類型不匹配) 開發階段即暴露,避免上線後靜默破壞數據完整性。
  2. 避免遷移災難:寬鬆模式下產生的髒數據,遷移到嚴格模式實例或異構資料庫時會大量報錯,修復成本極高。
  3. 數據質量底線:強制業務邏輯在應用層做校驗,資料庫只做最後一道防線,而非垃圾場。
  4. 標準兼容:符合 SQL 標準行為,利於異構遷移與團隊協作。

如何啟用?

方式一:配置文件永久生效 (推薦,一勞永逸)

[mysqld]
# MySQL 5.7 / 8.0 推薦組合
sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"

# 解釋:
# STRICT_TRANS_TABLES      : 事務表嚴格模式 (非事務表截斷仍警告,兼容性較好)
# NO_ENGINE_SUBSTITUTION   : 指定引擎不可用時不自動降級,直接報錯
# NO_ZERO_DATE             : 禁止 '0000-00-00' 日期
# NO_ZERO_IN_DATE          : 禁止月/日為 0 的日期 (如 2023-00-01)
# ERROR_FOR_DIVISION_BY_ZERO: 除零報錯而非返回 NULL

修改後 systemctl restart mysqld 生效。

方式二:會話級臨時生效 (測試/應急用)

SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO';
-- 或全局臨時 (重啟失效)
SET GLOBAL sql_mode = '...';

方式三:查看當前模式

SELECT @@sql_mode;           -- 當前會話
SELECT @@GLOBAL.sql_mode;    -- 全局

常見誤區與避坑

誤區真相
「嚴格模式會導致舊系統報錯無法運行」舊系統應修復代碼邏輯,而非降級資料庫。可先在測試環境開啟、修復代碼、再推生產。
「用 TRADITIONAL 模式最省事」TRADITIONAL 包含 STRICT_TRANS_TABLES 等,但過於激進 (含 NO_AUTO_CREATE_USER 等已廢棄項),建議顯式列出需要的模式。
「非事務表不受影響」STRICT_TRANS_TABLES 僅約束事務表;若全表皆為 InnoDB (預設),實際上全覆蓋。若有 MyISAM/MEMORY 表,考慮 STRICT_ALL_TABLES (慎用,影響面大)。
「ANSI 模式等同嚴格模式」ANSI 改變語法行為 (如 || 為字符串拼接),不等於嚴格數據校驗。

實戰驗證

CREATE TABLE `t_strict` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(10) NOT NULL,
  `age` TINYINT UNSIGNED NOT NULL,
  `created_at` DATETIME NOT NULL
) ENGINE=InnoDB;

-- 1. 字符串長度超限
INSERT INTO `t_strict` (`name`, `age`, `created_at`) VALUES ('這個名字太長了超過十個字符', 25, NOW());
-- ERROR 1406 (22001): Data too long for column 'name' at row 1

-- 2. 字符串塞入整型
INSERT INTO `t_strict` (`name`, `age`, `created_at`) VALUES ('test', 'abc', NOW());
-- ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'age'

-- 3. 非法日期
INSERT INTO `t_strict` (`name`, `age`, `created_at`) VALUES ('test', 25, '0000-00-00');
-- ERROR 1292 (22007): Incorrect datetime value: '0000-00-00'

-- 4. 除零
SELECT 1/0; -- ERROR 1365 (22012): Division by 0

總結

嚴格模式不是選項,是專業工程師的底線。 新專案初始化即配置;存量專案制定計劃:測試環境開啟 → 修復代碼/清洗數據 → 預發驗證 → 生產變更。別讓「寬容」成為技術債的溫床。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved