萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL CURRENT_TIMESTAMP 與 TIMESTAMP 類型深度解析:自動初始化、自動更新、版本差異與避坑

CURRENT_TIMESTAMP 基礎

SELECT CURRENT_TIMESTAMP, CURRENT_TIMESTAMP();
-- 2024-01-15 14:30:45

返回當前會話時區的日期時間,精度至秒(MySQL 5.6.4+ 支援毫秒 CURRENT_TIMESTAMP(3))。

TIMESTAMP 欄位預設值與自動更新行為

建表語法對照

定義INSERT 時UPDATE 時備註
ts TIMESTAMPCURRENT_TIMESTAMPCURRENT_TIMESTAMP隱性等同 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMPCURRENT_TIMESTAMP**不自動更新**僅初始化
ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP0000-00-00 00:00:00 (舊版) / NULL (新版)CURRENT_TIMESTAMP僅更新
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPCURRENT_TIMESTAMPCURRENT_TIMESTAMP完整自動維護
ts TIMESTAMP NULL DEFAULT NULLNULL不自動更新手動控制

實測範例

CREATE TABLE t1 (
    id INT PRIMARY KEY,
    ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;

INSERT INTO t1 (id) VALUES (1);           -- ts = 現在
SELECT * FROM t1;                         -- 1 | 2024-01-15 14:30:45
UPDATE t1 SET id = 2 WHERE id = 1;        -- ts 更新為現在
SELECT * FROM t1;                         -- 2 | 2024-01-15 14:31:10

TIMESTAMP vs DATETIME 選型指南

特性TIMESTAMPDATETIME
儲存空間4 bytes5 bytes (5.6.4+) / 8 bytes (舊版)
範圍1970-01-01 ~ 2038-01-19 (UTC)1000-01-01 ~ 9999-12-31
時區轉換**存儲時轉 UTC,讀取轉會話時區**不轉換,原樣存儲
自動初始化/更新支援5.6.5+ 支援
索引效能略優(整數比較)標準

關鍵陷阱與避坑指南

1. 2038 年問題

TIMESTAMP 以 32 位有號整數存儲 UTC 秒數,2038-01-19 03:14:07 UTC 後溢位。**長期專案務必用 DATETIME 或 BIGINT 存毫秒時間戳**。

2. 時區陷阱

SET time_zone = '+08:00';
INSERT INTO t (ts) VALUES (NULL);  -- 存入 UTC 時間
SET time_zone = '-05:00';
SELECT ts FROM t;  -- 顯示轉換後的 -05:00 時間

應用層**統一使用 UTC** 存儲與傳輸,前端按用戶時區顯示。

3. 多個 TIMESTAMP 欄位只第一個自動更新

CREATE TABLE t (
    created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

只有第一個 TIMESTAMP 欄位享有隱性 DEFAULT CURRENT_TIMESTAMP,第二個需顯式聲明。建議**所有 TIMESTAMP 欄位顯式聲明預設值**,避免隱性行為差異。

4. UPDATE 不改變值時不觸發自動更新

UPDATE t SET col = col WHERE id = 1;  -- 值未變,ts 不更新

若需強制更新時間戳,需顯式 SET ts = CURRENT_TIMESTAMP。

5. sql_mode 影響零日期處理

NO_ZERO_DATE 模式下 0000-00-00 非法,嚴格模式會報錯。建議欄位定義 NULL DEFAULT NULL 而非依賴零日期。

最佳實踐模板

CREATE TABLE events (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -- 建立時間:寫入一次永不變
    created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
    -- 更新時間:每次修改自動刷新
    updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
    -- 業務時間:由應用層指定,不依賴資料庫自動行為
    event_time DATETIME(3) NOT NULL,
    -- 軟刪除時間
    deleted_at DATETIME(3) NULL DEFAULT NULL,
    INDEX idx_created (created_at),
    INDEX idx_updated (updated_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • 統一用 DATETIME(3) 毫秒精度,規避 2038 年問題。
  • 明確語義分離:created_at(審計)、updated_at(樂觀鎖/同步)、event_time(業務)、deleted_at(軟刪)。
  • 應用層寫入時**不傳遞** created_at/updated_at,讓資料庫自動維護。

總結

TIMESTAMP 自動初始化/更新功能強大但暗藏時區、2038年、隱性預設值等陷阱。現代應用**首選 DATETIME(3) 顯式定義**,語義清晰、跨時區安全、長期可維護。僅在極度在意 4 bytes 存儲、確定不跨 2038 年、單時區部署的舊系統繼續使用 TIMESTAMP。

copyright © 萬盛學電腦網 all rights reserved