MySQL 5.7同实例同结构表不同Schema插入smallint(6)行为差异排查
问题根源与解决方案
核心原因:表级sql_mode差异
MySQL 5.7有个容易被忽略的特性:表创建时会继承当时会话的sql_mode,并把这个设置存在表的元数据里。之后对该表的所有写入操作,都会优先用这个表级的sql_mode,哪怕全局或当前会话的sql_mode已经变更。
你的两个表结构相同,但创建时的会话环境不一样:
- 新Schema的表创建时,会话开启了严格模式(包含
STRICT_TRANS_TABLES或STRICT_ALL_TABLES),所以插入超出smallint范围的值直接触发溢出错误。 - 另一个表创建时,会话未开启严格模式,超出范围的值会被自动截断到
smallint的最大值32767。
验证步骤
执行以下SQL,对比两个表的表级设置:
SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_OPTIONS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('表名1', '表名2');
查看TABLE_OPTIONS字段,里面会显示该表创建时的sql_mode内容,可直接确认差异所在。
统一行为的方法
如果要让两个表的处理逻辑一致,可以修改目标表的sql_mode:
- 先查询全局
sql_mode作为参考:
SELECT @@GLOBAL.sql_mode;
- 用
ALTER TABLE重建表并更新sql_mode:
ALTER TABLE 目标表名 ENGINE=InnoDB SQL_MODE='你要设置的sql_mode值';
⚠️ 注意:修改引擎会触发表重建,操作前记得备份数据。
关于用户级设置
MySQL 5.7没有原生的用户级sql_mode配置,但可以通过init_connect参数给指定用户设置登录时自动执行SET sql_mode=...,不过这不是你遇到的问题的原因——你的问题完全是表创建时的sql_mode遗留导致的。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

