创建表并插入数据:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `aaa`;
CREATE TABLE `aaa` (
`Id` int NOT NULL AUTO_INCREMENT,
`DataA` datetime(6) NOT NULL,
PRIMARY KEY (`Id`) USING BTREE
) AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
INSERT INTO `aaa` VALUES (1, '2026-05-15 11:17:08.000000');
INSERT INTO `aaa` VALUES (2, '2026-05-15 11:17:08.999999');
INSERT INTO `aaa` VALUES (3, '9999-12-31 23:59:59.999999');
SET FOREIGN_KEY_CHECKS = 1;
修改列类型:
ALTER TABLE `aaa`
MODIFY COLUMN `DataA` datetime NOT NULL AFTER `Id`;
MySQL执行结果:
1441 - Datetime function: datetime field overflow
Oceanbase结果
执行成功,查询数据:
+------+---------------------+
| Id | DataA |
+------+---------------------+
| 1 | 2026-05-15 11:17:08 |
| 2 | 2026-05-15 11:17:09 |
| 3 | NULL |
+------+---------------------+
诡异的是
select * from `aaa` where DataA is null;
竟然查不出结果,明明看到了null
UPDATE `aaa` SET `DataA` = '2026-05-15 11:30:56' WHERE `Id` = 3;
执行结果:
这个比较奇怪,我有两个集群,版本都是4.3.5.1,但是一个两副本集群执行结果为:
4377 - fatal internal error in [check_datum_row_nullable_value]
另外一个执行就成功,能够正常更新,这个很奇怪,为什么呢?
总结
在datetime(6)转到datetime的时候,时间会进行四舍五入,但是对于9999-12-31 23:59:59.999999,再入的话就成为一个非法值了。MySQL的策略是不让你改,Oceanbase的策略是你只管改,但是数据给你破坏掉。 把它设置null(虽然表结果规定了该列不可为null),我觉得还是应该安全一些。这种情况不让你改比较好,否则在不知情的情况下业务挂掉是很危险的事情。数据库最重要的就是数据了,溢出了应该不让你改才对,设置null也要看列能不能为null