MariaDB中DEFAULT CURRENT_TIMESTAMP未生效问题求助
先别慌,咱们一步步来排查和解决这个问题:
1. 先确认功能是否真的未生效
有时候GUI工具(比如HeidiSQL)的显示会有偏差,不如直接用SQL语句查看表的真实定义更靠谱:
SHOW CREATE TABLE ids;
执行这条命令后,看输出的建表语句里,lastupdate列的定义是否包含DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。如果有,说明数据库层面已经正确配置了,只是HeidiSQL没显示对,这时候可以用实际操作验证:
- 插入一条不指定
lastupdate的记录:INSERT INTO ids (id) VALUES (NULL);(因为id是自增的,传NULL会自动生成值) - 查看这条记录的
lastupdate,应该是当前时间 - 更新这条记录:
UPDATE ids SET id=id WHERE id=1;(这里用id=id不改变数据,但能触发更新操作) - 再看
lastupdate,如果自动更新成了当前时间,那说明功能是正常的,只是HeidiSQL的显示bug。
2. 如果实际确实未生效,排查这几个点
问题1:建表语句的注释格式可能有问题
你的建表语句里用了# 该配置未生效作为行注释,虽然MariaDB支持#注释,但在列定义的逗号后直接加这种注释,偶尔会让解析器出现小异常。建议换成标准的SQL块注释格式,重新建表试试:
CREATE TABLE `ids` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `lastupdate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP /* 该配置未生效 */, PRIMARY KEY (`id`) ) COLLATE='utf8_general_ci' ENGINE=InnoDB ;
问题2:sql_mode的限制影响
检查当前的sql_mode设置,看看是否包含NO_DEFAULT_TIMESTAMP(这个模式会强制要求NOT NULL的TIMESTAMP列必须显式指定默认值,不过你的表已经创建成功,这个可能性偏低,但还是排查下):
SELECT @@sql_mode;
如果结果里有NO_DEFAULT_TIMESTAMP,可以修改配置文件(Linux是my.cnf,Windows是my.ini),去掉这个模式,然后重启MariaDB服务。修改后的sql_mode示例:
sql_mode = "STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
问题3:旧版本的MariaDB bug
你用的10.2.13是2018年的老版本,可能存在TIMESTAMP默认值相关的已知bug。如果上面的方法都没用,建议升级到10.2系列的最新稳定版(比如10.2.44),或者直接升级到更高的分支(比如10.4+),新版本修复了很多旧问题。
3. 替代方案:用触发器实现相同功能
如果以上方法都走不通,可以用触发器来模拟DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的效果:
插入触发器(设置默认时间)
DELIMITER // CREATE TRIGGER trg_ids_insert_lastupdate BEFORE INSERT ON ids FOR EACH ROW BEGIN IF NEW.lastupdate IS NULL THEN SET NEW.lastupdate = CURRENT_TIMESTAMP; END IF; END // DELIMITER ;
更新触发器(自动更新时间)
DELIMITER // CREATE TRIGGER trg_ids_update_lastupdate BEFORE UPDATE ON ids FOR EACH ROW BEGIN SET NEW.lastupdate = CURRENT_TIMESTAMP; END // DELIMITER ;
这样不管插入还是更新记录,lastupdate都会自动同步为当前时间,和原生配置的效果完全一致。
内容的提问来源于stack exchange,提问作者Kittsil

