确认严格模式是否启用需执行select @@sql_mode并检查是否含strict_trans_tables;mysql 8.0+虽默认开启,但phpmyadmin、laravel等可能连接后覆盖,必须查运行时值;持久生效须修改my.cnf中[mysqld]段sql_mode并重启服务,不可仅依赖set global或客户端设置。

确认当前 sql_mode 是否已启用严格模式
直接执行 SELECT @@sql_mode;,看返回值里是否包含 STRICT_TRANS_TABLES。MySQL 8.0+ 虽默认开启该选项,但 phpMyAdmin、Laravel 或某些连接池可能在建连后覆盖它,导致实际不生效。别只信配置文件或文档描述,必须查运行时值。
用 my.cnf 持久化配置 STRICT_TRANS_TABLES(推荐)
临时 SET 语句(如 SET GLOBAL sql_mode=...)重启即失效,且部分客户端(如 PHP PDO)会主动重设,不可靠。真正生效得改配置文件:
- 编辑
/etc/mysql/my.cnf或/etc/my.cnf,在[mysqld]段下添加或修改这一行:sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION" - 删掉
ONLY_FULL_GROUP_BY——它常和业务 SQL 冲突,不是严格模式必需项 - 避免加
STRICT_ALL_TABLES:MyISAM 表出错无法回滚,会导致半写入脏数据 - 改完必须重启 MySQL:
sudo systemctl restart mysql,光 reload 不生效
验证是否真生效:用插入测试堵住静默截断
配置完别只查 @@sql_mode,要实测行为:
- 建一张测试表:
CREATE TABLE t (s VARCHAR(5) NOT NULL); - 执行
INSERT INTO t VALUES ('abcdef');—— 严格模式下应报ERROR 1406 (22001): Data too long for column 's',而非仅警告 + 截成 'abcde' - 再试日期:
INSERT INTO t2 (d) VALUES ('0000-00-00');,若配了NO_ZERO_DATE,也应报错,不是转成NULL或默认值
Laravel / PHP 连接后 sql_mode 被悄悄覆盖怎么办
很多框架在 PDO 连接建立后自动执行 SET sql_mode = ...,可能把服务器端配置给顶掉。此时 SELECT @@sql_mode 在连接内看到的值 ≠ 服务器全局值。
- 检查连接后的实际值:
SELECT @@sql_mode必须在你应用的数据库连接里执行,不是在 mysql 命令行 - 不要在 Laravel 的
database.php里用PDO::MYSQL_ATTR_INIT_COMMAND去 SET,尤其别写清除 strict 的逻辑 - 唯一可靠解法:MySQL 侧固化配置 + 禁用所有客户端的 sql_mode 覆盖(如 MySQL 8.0.31+ 可设
sql_mode为只读变量,需 DBA 权限)











