MySQL TIMESTAMP 的默認值與 ON UPDATE 行為存在大量隱式規則,稍有不慎即陷入「時間不更新」「唯一索引衝突」「建表報錯」等坑。本文通過 8 個遞進實驗,系統揭示 TIMESTAMP 隱式屬性、單列限制、修改姿勢,助你精準掌控時間列行為。
| 規則 | 說明 | 版本差異 |
|---|---|---|
| 規則 1 | 表中第一個 TIMESTAMP 列,若無顯式定義,隱式擁有 NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 5.6.5 前默認行為 |
| 規則 2 | 一張表僅允許一個 TIMESTAMP 列擁有 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 屬性 | 所有版本 |
| 規則 3 | 顯式定義 DEFAULT CURRENT_TIMESTAMP 或 DEFAULT 0 可覆蓋隱式行為 | 5.6.5+ 支援顯式關閉自動更新 |
| 規則 4 | UPDATE 設置列為當前值時,MySQL 為效率忽略更新,不觸發 ON UPDATE | 所有版本 |
CREATE TABLE dj1 (a CHAR(1), b TIMESTAMP, c TIMESTAMP);
INSERT INTO dj1 VALUES (1,NULL,NULL), (2,NULL,NULL);
-- 結果:b、c 均為 INSERT 時刻,b 具備 ON UPDATE 自動更新,c 固定不變
UPDATE dj1 SET a=9 WHERE a=1;
-- b 變為更新時刻,c 保持插入時刻
UPDATE dj1 SET a=8 WHERE a=2;
-- b 再次更新,c 不變
CREATE UNIQUE INDEX dj1_idx_u1 ON dj1(b);
UPDATE dj1 SET a=1; -- ERROR 1062: Duplicate entry '2009-09-09 13:54:45' for key 'dj1_idx_u1'
-- 原因:所有行 b 同時更新為同一秒時間戳,唯一索引衝突
SHOW CREATE TABLE 看隱式屬性SHOW CREATE TABLE dj1\G
-- b: timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
-- c: timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
CREATE TABLE dj2 (a CHAR(1), b TIMESTAMP DEFAULT CURRENT_TIMESTAMP, c TIMESTAMP DEFAULT '0000-00-00 00:00:00');
-- 更新 dj2 不再觸發 b 自動更新,唯一索引無衝突
CREATE TABLE dj3 (b TIMESTAMP DEFAULT CURRENT_TIMESTAMP, c TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
-- ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
-- dj4: b DEFAULT CURRENT_TIMESTAMP, c DEFAULT '0' ON UPDATE CURRENT_TIMESTAMP → 1293
-- dj5: b DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, c DEFAULT CURRENT_TIMESTAMP → 1293
-- 1. 查看當前定義
SHOW CREATE TABLE tbl_ledgerrecord\G
-- 2. 移除自動更新,僅保留插入時默認
ALTER TABLE tbl_ledgerrecord
CHANGE intoStorageDate intoStorageDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
-- 3. 完全關閉自動屬性(需 5.6.5+)
ALTER TABLE tbl_ledgerrecord
CHANGE intoStorageDate intoStorageDate TIMESTAMP DEFAULT '0000-00-00 00:00:00';
-- 4. 明確指定 ON UPDATE(僅限非第一個 TIMESTAMP 列)
ALTER TABLE tbl_ledgerrecord
CHANGE updateTime updateTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
DEFAULT 與 ON UPDATEcreated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP(無 ON UPDATE)updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(放在第 2+ 位)updated_at 絕不可加唯一索引,高併發必衝突MySQL TIMESTAMP 的「第一列自動獲得 ON UPDATE」「全表僅一列可用 CURRENT_TIMESTAMP」兩大隱式規則,是無數遷移故障與詭異 Bug 的根源。顯式定義、錯位放置、拒絕唯一索引 三原則,讓時間列行為完全可控、可預測、可維護。