datetime與timestamp的區別
1、存儲空間不同
在MySQL,timestamp在內部存儲爲整型,佔用4個字節,而datetime佔用8個字節。
2、存儲方式不同
timestamp存儲時,會從插入時間的客戶端時區轉換爲UTC(世界標準時間)時間存儲,而datetime不會做時間的轉換直接存儲。
3、存儲的時間範圍不同
- timestamp:UTC時間,1970-01-01 00:00:01.000000到 2038-01-19 03:14:07.999999
- datetime:與時區無關,1000-01-01 00:00:00.000000 到 9999-12-31 23:59:59.999999
4、自動更新
在同一個表裏,允許有一個字段自動更新時間。如
CREATE TABLE `tb` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`mydatetime` datetime DEFAULT NULL,
`mytimestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
其中,mytimestamp爲自動更新時間,ON UPDATE CURRENT_TIMESTAMP。
使用選擇
在datetime和timestamp這幾個不同裏,存儲方式和時間範圍的不同會影響到我們對兩個類型的選擇。
timestamp始終會存儲爲UTC時間,也就是說它是一個固定時間,只是在不同的時區表示不同而已。而datetime則是一個靜態的時間,與時區無關。
在使用選擇上需要知道不同的存儲方式會帶來的問題
問題一
在跨時區做數據遷移,datetime類型的數據不能自動修正,需要我們使用其他方式做數據修正。因爲它是一個靜態的時間。
示例
CREATE TABLE `time_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`mydatetime` datetime DEFAULT NULL,
`mytimestamp` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
查看系統時區
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | SYSTEM |
+------------------+--------+
往time_test插入數據
mysql>INSERT INTO time_test (mydatetime,mytimestamp) VALUES (NOW(),NOW());
mysql>SELECT * FROM time_test;
+----+---------------------+---------------------+
| id | mydatetime | mytimestamp |
+----+---------------------+---------------------+
| 1 | 2017-12-08 22:14:56 | 2017-12-08 22:14:56 |
+----+---------------------+---------------------+
修改時區
mysql>SET time_zone='+9:00';
mysql>SELECT * FROM time_test;
+----+---------------------+---------------------+
| id | mydatetime | mytimestamp |
+----+---------------------+---------------------+
| 1 | 2017-12-08 22:14:56 | 2017-12-08 23:14:56 |
+----+---------------------+---------------------+
把時區修改爲“+9:00”,即東九區,mytimestamp時間顯示比之前多了一個小時。而mydatetime沒有變化
繼續插入一行數據
mysql>INSERT INTO time_test (mydatetime,mytimestamp) VALUES (NOW(),NOW());
mysql>SELECT * FROM time_test;
+----+---------------------+---------------------+
| id | mydatetime | mytimestamp |
+----+---------------------+---------------------+
| 1 | 2017-12-08 22:14:56 | 2017-12-08 23:14:56 |
| 2 | 2017-12-08 23:17:53 | 2017-12-08 23:17:53 |
+----+---------------------+---------------------+
注意,此時爲東九區,mydatetime插入的也是東九區當時的時間,而第一行數據仍然爲舊的數據。
修改爲東八區
mysql>SET time_zone='+8:00';
mysql>INSERT INTO time_test (mydatetime,mytimestamp) VALUES (NOW(),NOW());
mysql>SELECT * FROM time_test;
+----+---------------------+---------------------+
| id | mydatetime | mytimestamp |
+----+---------------------+---------------------+
| 1 | 2017-12-08 22:14:56 | 2017-12-08 22:14:56 |
| 2 | 2017-12-08 23:17:53 | 2017-12-08 22:17:53 |
+----+---------------------+---------------------+
此時,mytimestamp兩個時間都顯示爲東八區的時間,而mydatetime還是原來插入的時間。
問題二
timestamp所能表示的時間範圍小:UTC時間,1970-01-01 00:00:01.000000到 2038-01-19 03:14:07.999999
解決
timestamp所能表示的時間範圍小是MySQL設計上決定的,我們在應用層解決不了。datetime在跨時區的問題我們可以在應用層解決。
解決的思路和存儲timestamp的方式是一樣的,在應用層把datetime的時間統一轉爲UTC,然後我們再存進MySQL。如果需要在不同時區顯示,只需要在應用層把UTC時間轉換爲時區時間即可。