首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL DATETIME vs TIMESTAMP 深度對比:選型指南與避坑手冊

     編輯:MySQL 綜合教學

核心差異速覽表

特性DATETIMETIMESTAMP
存儲字節8 bytes (5.6.4 前) / 5 bytes + 小數秒 (5.6.4+)4 bytes (5.6.4 前) / 4 bytes + 小數秒 (5.6.4+)
時間範圍1000-01-01 00:00:00 ~ 9999-12-31 23:59:591970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC
時區感知無 (存儲字面值)有 (存儲 UTC,讀取按會話時區轉換)
自動初始化/更新5.6.5+ 支持 DEFAULT CURRENT_TIMESTAMP / ON UPDATE CURRENT_TIMESTAMP首個 TIMESTAMP 列默認自動初始化/更新,可顯式控制
NULL 值處理不自動賦值插入 NULL 等同於 CURRENT_TIMESTAMP
Java 映射java.sql.Timestamp / java.time.LocalDateTimejava.sql.Timestamp / java.time.Instant
索引/查詢性能略低 (佔用空間大)略高 (佔用空間小)

關鍵行為差異詳解

1. 時區轉換陷阱 (TIMESTAMP 獨有)

-- 會話時區為 +08:00
INSERT INTO t(ts_col) VALUES ('2024-01-01 12:00:00'); -- 存儲為 UTC: 2024-01-01 04:00:00
SELECT ts_col FROM t; -- 讀出顯示: 2024-01-01 12:00:00 (按會話時區轉回)

-- 若會話時區變為 +00:00 再查
SET time_zone = '+00:00';
SELECT ts_col FROM t; -- 顯示: 2024-01-01 04:00:00  <-- 數據「變了」!

結論:跨時區應用、數據遷移、備份恢復時,TIMESTAMP 會隨時區變化而「變值」,DATETIME 絕不變。需業務無時區敏感性才用 TIMESTAMP。

2. 2038 年問題 (TIMESTAMP 硬傷)

32 位有符號整數存儲秒數,上限 2038-01-19。長期項目(銀行、保單、日志審計)**禁用 TIMESTAMP 作為業務時間**,必須用 DATETIME 或 BIGINT 毫秒時間戳。

3. 自動更新機制演進

  • 5.5 及之前:僅首個 TIMESTAMP 列支持 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP,且二擇一
  • 5.6.5+:所有 TIMESTAMP/DATETIME 列均支持任意組合,DEFAULT CURRENT_TIMESTAMP + ON UPDATE CURRENT_TIMESTAMP 可共存

選型決策樹

  1. 需存儲 2038 年後或 1970 年前的時間? → DATETIME
  2. 業務涉及多時區、跨地域部署? → DATETIME (應用層統一存 UTC) 或 BIGINT 毫秒戳
  3. 僅需記錄「記錄創建/修改時間」,單時區、短期項目? → TIMESTAMP (節省空間、自動維護)
  4. 高寫入併發、極致性能敏感? → TIMESTAMP (4 bytes 索引更緊湊)
  5. 需精確到毫秒/微秒 (5.6.4+)? → 兩者均支持 DATETIME(3) / TIMESTAMP(3)

最佳實踐建議

  • 統一用 DATETIME(3) 或 BIGINT:消除時區困擾、規避 2038 問題、應用層掌控時間邏輯
  • 應用層統一 UTC:寫入前統一轉 UTC,讀出後按用戶時區展示,數據庫層不做時區轉換
  • 避免依賴數據庫自動更新:應用層顯式設置 created_at、updated_at,邏輯清晰可控
  • 備份/遷移工具需識別類型:mysqldump 導出 TIMESTAMP 會按會話時區轉換,跨時區恢復需加 --tz-utc 參數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved