You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL生成列引用CURRENT_TIMESTAMP插入失败的差异问题排查

MySQL 8.0.24+ 生成列非空约束报错问题分析与解决

问题场景

表结构定义如下:

CREATE TABLE t3 (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `abc` bigint NOT NULL,
  `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `createdday` int GENERATED ALWAYS AS (cast(`ts` as date)) STORED NOT NULL,
  PRIMARY KEY (`id`)
);

在两个同版本(8.0.25)的MySQL实例中执行insert into t3 (abc) values (2);时,出现差异:

  • 一个实例可成功写入,createdday值符合预期;
  • 另一个实例报错:ERROR 1048 (23000): Column 'createdday' cannot be null。

已确认两个实例explicit_defaults_for_timestamp配置均为OFF,且经多版本测试发现:

  • MySQL 8.0.23中该插入语句可正常执行;
  • 升级至8.0.24后开始出现非空错误,推测问题始于8.0.24版本。对应官方bug列表中的相关问题,但暂无修复更新。

原因分析

核心原因是MySQL 8.0.24对生成列的非空约束校验时机做了调整:

  • 8.0.23及更早版本:生成列的计算逻辑在ts列应用默认值(CURRENT_TIMESTAMP)之后执行,因此createdday能基于有效的ts值得到非空结果,通过非空校验;
  • 8.0.24+版本:非空约束校验被提前到生成列计算之前,此时ts的默认值尚未被填充,校验逻辑判定createdday为NULL,触发非空约束错误。

即使是同版本的实例,也可能因初始化细节、临时参数变更等隐性差异出现表现不一致,但本质都是8.0.24引入的校验逻辑变更导致的问题。

解决方法

方案1:调整生成列表达式,兼容校验时机

修改生成列表达式,通过COALESCE函数确保即使ts在校验阶段被视为NULL,也能返回有效日期值:

ALTER TABLE t3 MODIFY COLUMN createdday int GENERATED ALWAYS AS (COALESCE(cast(`ts` as date), CURRENT_DATE)) STORED NOT NULL;

方案2:插入时显式指定ts列值

绕过默认值填充的时机问题,插入时直接指定ts的值:

INSERT INTO t3 (abc, ts) VALUES (2, CURRENT_TIMESTAMP);

方案3:回退至8.0.23版本(业务允许的情况下)

如果业务对版本兼容性要求不高,可暂时回退到MySQL 8.0.23,等待官方修复该bug。

方案4:将存储列改为虚拟列

虚拟生成列(VIRTUAL)的计算时机晚于存储列,能避开提前校验的问题:

ALTER TABLE t3 MODIFY COLUMN createdday int GENERATED ALWAYS AS (cast(`ts` as date)) VIRTUAL NOT NULL;

内容的提问来源于stack exchange,提问作者sillydong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:27:16