首批通过分布式安全可靠测评,为关键业务系统打造
current_timestamp 列插入 default 值出现正确性问题
更新时间:2026-05-28 02:06
问题现象
向 timestamp default current_timestamp 列插入 default 值时,插入结果多 +08:00。
复现步骤如下。
创建表 t1,表包含两列,分别为 c1 和 c2,设置 c1 列数据类型为
int,c2 列的数据类型为timestamp默认值为current_timestamp,表示在插入数据时没有为该列指定值,系统会自动使用当前的时间戳作为默认值。obclient [test]> create table t1(c1 int, c2 timestamp default current_timestamp); Query OK, 0 rows affected (0.663 sec)向 t1 表 c1 列插入一条数据并查询,不设置 c2 列 values 值为 default,查询结果为
2023-06-28 20:11:22。obclient [test]> insert into t1 (c1) values(1); Query OK, 1 row affected (0.233 sec) obclient [test]> select * from t1; +------+---------------------+ | c1 | c2 | +------+---------------------+ | 1 | 2023-06-28 20:11:22 | +------+---------------------+ 1 row in set (0.030 sec)向 t1 表中插入第二条数据,并设置 c2 列 values 值为 default,查询结果为
2023-06-29 04:11:22,查询结果比原来多加 8 小时与预期的值不符。obclient [test]> insert into t1 (c1,c2) values(2, default); Query OK, 1 row affected (0.009 sec) obclient [test]> select * from t1; +------+---------------------+ | c1 | c2 | +------+---------------------+l | 1 | 2023-06-28 20:11:22 | | 2 | 2023-06-29 04:11:22 | +------+---------------------+ 2 rows in set (0.002 sec)
问题原因
OceanBase 数据库 V3.x 版本新引擎引入的问题,default 表达式没有对参数进行 cast,参数 current_timestamp 输出的结果是 datetime 类型,default 直接取参数的值并且将其解释为 timestamp 类型。
除 current_timestamp 和 now() 之外的其他场景没有问题,比如 default 值是个字符串,列类型是 int,那么 default 表达式的参数会由字符串转成 int 类型。
问题的风险及影响
导致插入的值与预期的值不符。
影响版本
- OceanBase 数据库企业版 V3.1.2 BP11(oceanbase-3.1.2-111000052023010412)、V3.2.3 BP8(oceanbase-3.2.3.3-108000062023041511)、V3.2.4 BP4 Hotfix1(oceanbase-3.2.4.4-104010012023062711)、V4.1.0 BP2(oceanbase-4.1.0.1-102000042023061309)及之前版本。
- OceanBase 数据库社区版 V3.x 所有版本。
解决方法及规避方式
解决方法
订正插入的错误数据,以 time_zone = '+8:00' 或 'Asia/Shanghai' 为例。
update t set c_timestamp = from_unixtime(unix_timestamp(c_timestamp) - 8 * 3600);如果知道出问题的时间范围,可以在
where条件中加上过滤条件。升级到问题已修复版本,目前已修复的版本包括 OceanBase 数据库 V3.2.3 BP9(oceanbase-3.2.3.3-109000182023071410)、V3.2.4 BP4 Hotfix2(oceanbase-3.2.4.4-104020012023070316)、V4.1.0 BP2 Hotfix1(oceanbase-4.1.0.1-102010012023062910)及之后版本。
规避方式
暂无规避方式,但您可以通过如下方式巡查。
检查 default 值为 current_timestamp 或 now,并且类型是 timestamp 的列,从 sql_audit 中查看是否有 insert或 update 指定这个列的值为 DEFAULT。