ci3 的 stricton=true 仅控制连接异常抛出,不启用 mysql 严格模式;真正约束数据需配置 sql_mode(如 strict_trans_tables),并分层校验。

CI3 中把数据库配置的 stricton 设为 true,表面上是开启“严格模式”,实则容易引发隐性报错、写入失败甚至业务静默中断——这不是推荐做法,反而是个典型误区。
stricton=true 并非开启 SQL 严格模式
CI3 的 stricton 是 CodeIgniter 自己的连接开关,和 MySQL 的 sql_mode 无关。它只控制 CI 是否在连接失败时抛出异常(true 会 throw error;false 则静默返回 false)。设为 true 后:
- 数据库服务短暂不可用、超时或权限不足时,整个请求直接 500,无兜底逻辑
- 某些云数据库或中间件(如 ProxySQL)返回非标准握手响应,CI 会误判为连接失败
- 不解决任何数据校验问题,比如插入空字符串到 NOT NULL 字段、零日期、除零等依然照常入库(除非 MySQL 本身已配 STRICT 模式)
真正影响数据行为的是 MySQL 的 sql_mode
CI3 的 stricton 对 SQL 执行过程零干预。要约束非法数据,必须调整 MySQL 层面的 sql_mode,例如:
- 启用
STRICT_TRANS_TABLES:对事务表强制类型校验,超长截断变报错,字符串转数字失败直接拒绝插入 - 禁用
NO_ZERO_DATE和NO_ZERO_IN_DATE:否则 '0000-00-00' 类日期会被拒 - CI3 中需手动在连接后执行:
$this->db->query('SET sql_mode = "STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO"');
常见连锁故障场景
当误以为 stricton=true 能防脏数据,又没配 MySQL 严格模式时:
- 前端传来字符串
"abc"插入 INT 字段 → MySQL 默认转成0入库,业务逻辑误判为合法 ID - 时间字段填了
"2026-02-30"→ 自动转成"0000-00-00",后续 WHERE date > '2025-01-01' 查询漏掉该行 - UPDATE 语句中 SET price = '' → 变成
0,订单金额被清零,且无任何警告
正确姿势:分层控制 + 显式设置
不要依赖 CI 的 stricton 做数据治理。稳妥做法是:
- CI3 配置保持
'stricton' => FALSE(保障连接韧性) - 在数据库初始化阶段统一执行
SET sql_mode,或在 MySQL 配置文件中全局设定 - 应用层做输入校验(如使用 CI 表单验证类),不把校验责任全推给数据库
- 关键写入后加
$this->db->affected_rows()检查是否真写入,避免静默失败











