PAYATHON 2026

MySQL 如何为 INT 字段设置当前 Unix 时间戳默认值并排查 504?

数据阿明

如果数据库服务器是 MySQL 8.0.13 或更高版本,且存储引擎支持表达式默认值,可以使用 DEFAULT (UNIX_TIMESTAMP())。原 SQL 中的函数调用外还需要加一层括号。请求最终返回 504 的原因,仅凭现有信息无法确定,还需要检查数据库的执行状态。

先确认 MySQL 服务器版本

mysqlnd 8.3.30 是 PHP 客户端驱动的版本信息,不能用来判断 MySQL 服务器版本。关于 mysqlnd 的作用,可参见 PHP 官方说明。

连接目标数据库后执行:

SELECT VERSION();
SHOW CREATE TABLE `table`;

第一条查询用于确认服务器版本,以及服务器是否为其他兼容数据库;第二条用于检查字段定义和存储引擎。下文以 MySQL 为前提,其他兼容数据库需要核对各自的语法支持。

正确设置当前 Unix 时间戳默认值

MySQL 从 8.0.13 开始支持表达式默认值,通常要求在表达式外加括号。UNIX_TIMESTAMP() 自身的函数括号不能代替这一层括号。具体限制见 MySQL 默认值文档。

如果字段确实应定义为 INT NOT NULL,可以使用:

ALTER TABLE `table`
MODIFY COLUMN `time_upd` INT NOT NULL
DEFAULT (UNIX_TIMESTAMP());

将 table 替换为实际表名。如果实际表名就是 table,保留反引号。

执行前先核对原字段属性。MODIFY COLUMN 会重新声明字段定义,需要保留的 UNSIGNED、COMMENT 等属性也应一并写入,否则可能被改变或丢失。相关行为见 ALTER TABLE 文档。

修改后再次执行:

SHOW CREATE TABLE `table`;

确认默认值已写入表定义。插入记录时,省略 time_upd 或为它指定 DEFAULT,才会使用该默认值;显式传入 0 或其他数值时,会使用传入的值。此次修改也不会把已有记录统一更新为当前时间。

504 应如何排查

504 表示网关或代理等待上游响应超时,本身不是 MySQL 的 SQL 错误码,参见 HTTP 504 定义。仅凭 504 无法判断 SQL 是否执行失败,也不能断定一定发生了锁等待。

请求卡住时,从另一个数据库连接执行:

SHOW FULL PROCESSLIST;

找到对应的 ALTER TABLE,重点检查 State、Time 和 Info。

  • 如果状态为 Waiting for table metadata lock,说明正在等待表的元数据锁。访问过该表但尚未结束的事务可能阻塞 DDL,需要查明阻塞会话,再由相关业务连接提交或回滚事务。
  • 如果语句仍在执行,可以结合表结构、数据量和服务器负载判断耗时原因。
  • 如果已经找不到该语句,检查应用或数据库管理工具记录的错误,并用 SHOW CREATE TABLE 确认修改是否完成。

MySQL 官方文档提供了使用 SHOW FULL PROCESSLIST 识别元数据锁等待的示例,见 Online DDL 并发说明。

也可以通过 MySQL 命令行客户端执行修正后的 SQL,直接获取数据库返回的信息。重试前先确认上一次操作的状态;单纯延长 HTTP 超时无法解决数据库锁等待。

旧版本和自动更新时间的处理

如果服务器早于 MySQL 8.0.13,不能给 INT 字段设置这种函数表达式默认值。可以在插入语句中显式写入时间戳,或使用 BEFORE INSERT 触发器赋值。例如,下列语句仅展示目标字段,实际使用时应补齐其他必填字段:

INSERT INTO `table` (`time_upd`)
VALUES (UNIX_TIMESTAMP());

默认值只负责插入时的初始化。即使字段名叫 time_upd,它也不会因此在每次 UPDATE 时自动刷新。如果还需要记录更新时间,应在更新语句中显式赋值,或使用 BEFORE UPDATE 触发器。ON UPDATE CURRENT_TIMESTAMP 的自动更新能力适用于 TIMESTAMP 和 DATETIME,不能直接用于 INT,参见 MySQL 自动初始化与更新说明。

备注:内容仅供参考。