細說MySQL的時間戳 Timestamp 型別

2021-09-27 02:29:40 字數 3601 閱讀 9581

生產環境中部署著各種版本的mysql,包括mysql 5.5/5.6/5.7三個大版本和n個小版本,由於mysql在向上相容性較差,導致相同sql在不同版本上表現各異,下面從幾個方面來詳細介紹時間戳資料型別。

時間戳資料訪問

在mysql上述三個大版本中,預設時間戳(timestamp)型別的取值範圍為'1970-01-01 00:00:01' utc 至'2038-01-19 03:14:07' utc,資料精確到秒級別,該取值範圍包含約22億個數值,因此在mysql內部使用4個位元組int型別來存放時間戳資料:

1、在儲存時間戳資料時,先將本地時區時間轉換為utc時區時間,再將utc時區時間轉換為int格式的毫秒值(使用unix_timestamp函式),然後存放到資料庫中。

2、在讀取時間戳資料時,先將int格式的毫秒值轉換為utc時區時間(使用from_unixtime函式),然後再轉換為本地時區時間,最後返回給客戶端。

在mysql 5.6.4及之後版本,可以將時間戳型別資料最高精確微秒(百萬分之一秒),資料型別定義為timestamp(n),n取值範圍為0-6,預設為0,如需要精確到毫秒則設定為timestamp(3),如需要精確到微秒則設定為timestamp(6),資料精度提高的代價是其內部儲存空間的變大,但仍未改變時間戳型別的最小和最大取值範圍。

時間戳字段定義

時間戳字段定義主要影響兩類操作:

1、插入記錄時,時間戳字段包含default current_timestamp,如插入記錄時未指定具體時間資料則將該時間戳字段值設定為當前時間

2、更新記錄時,時間戳字段包含on update current_timestamp,如更新記錄時未指定具體時間資料則將該時間戳字段值設定為當前時間

ps1:current_timestamp表示使用current_timestamp()函式來獲取當前時間,類似於now()函式

根據上面兩類操作,時間戳列可以有四張組合定義,其含義分別為:

1、當欄位定義為timestamp,表示該字段在插入和更新時都不會自動設定為當前時間。

2、當欄位定義為timestamp default current_timestamp,表示該字段僅在插入且未指定值時被賦予當前時間,再更新時且未指定值時不做修改。

3、當欄位定義為timestamp on update current_timestamp,表示該字段在插入且未指定值時被賦值為"0000-00-00 00:00:00",在更新且未指定值時更新為當前時間。

4、當欄位定義為timestamp default current_timestamp on update current_timestamp,表示該字段在插入或更新時未指定值,則被賦值為當前時間。

ps1:在mysql中執行的建表語句和最終表建立語句會存在差異,建議使用show create table tb_***獲取已建立表的建表語句。

時間戳字段在mysql各版本的使用差異

1、在mysql 5.5及之前版本中,僅能對乙個時間戳字段定義defualt current_timestamp或on update current_timestamp,但在mysql 5.6和mysql 5.7版本中取消了該限制;

2、在mysql 5.6版本中引數explicit_defaults_for_timestamp預設值為1,在mysql 5.7版本中引數explicit_defaults_for_timestamp預設值為0;

3、在mysql 5.5和mysql 5.7版本中timestamp型別預設為not null,在在mysql 5.6版本中timestamp型別預設為null;

4、當建表語句中定於c1 timestamp 時,

在mysql 5.5中等價於`c1` timestamp not null default current_timestamp on update current_timestamp;

在mysql 5.6中等價於`c1` timestamp null default null;

在mysql 5.7中等價於`c1` timestamp not null default current_timestamp on update current_timestamp;

5、當建表語句中c1 timestamp default 0時,

在mysql 5.5中等價於`c1` timestamp not null default '0000-00-00 00:00:00';

在mysql 5.6中等價於`c1` timestamp null default '0000-00-00 00:00:00';

在mysql 5.7中等價於`c1` timestamp not null default '0000-00-00 00:00:00';

ps1: mysql 5.6版本和mysql 5.7版本中主要差異受引數explicit_defaults_for_timestamp的預設值影響。

ps2:當時間戳列的預設值為'0000-00-00 00:00:00'時,使用「不在時間戳取值範圍內」的該預設值並不會產生警告。

時間戳型別引發的異常

當mysql引數time_zone=system時,查詢timestamp欄位會呼叫系統時區做時區轉換,而由於系統時區存在全域性鎖問題,在多併發大資料量訪問時會導致執行緒上下文頻繁切換,cpu使用率暴漲,系統響應變慢設定假死。

時間戳型別和時間型別選擇

在部分"資料庫指導"文件中,會推薦使用timestamp型別代替datetime欄位,其理由是timestamp型別使用4位元組,而datetime欄位使用8位元組,但隨著磁碟效能提公升和記憶體成本降低,在實際生產環境中,使用timestamp型別並不會帶來太多效能提公升,反而可能因timestamp型別的定義和取值範圍限制和影響業務使用。

在mysql 5.6.4及之後版本,可以將時間戳型別(timestamp)資料最高精確微秒,也同樣可以將時間型別(datetime)資料最高精確微秒,時間型別(datetime)同樣可以獲得timestamp型別相同的效果,如將字段定義為 dt1 datetime(3) not null default now(3) on update now(3); 時間型別(datetime)的訪問範圍'1000-01-01 00:00:00.000000' 至 '9999-12-31 23:59:59.999999',能更好地存放各時間段的資料。

時間戳型別使用建議

1、在只關心資料最後更新時間的情況下,建議將時間戳列定義為timestamp not null default current_timestamp on update current_timestamp;

2、在關心建立時間和更新時間的情況下,建議將更新時間設定為時間戳字段,將建立時間定義為daetime 或 timestamp default '0000-00-00 00:00:00',並在插入記錄時顯式指定建立時間;

3、建議在表中只定義單個時間戳列,並顯式定義default 和 on update屬性;

4、雖然在mysql中可以對時間戳字段賦值或更新,但建議僅在必要的情況下對時間戳列進行顯式插入和更新;

5、建議將time_zone引數設定為system外的值,如中國地區伺服器設定為'+8:00';

6、建議將mysql線下測試版本和線上生產版本保持一致。

datetime和time的時間戳用法

from datetime import datetime print datetime.now 本地時間 print datetime.utcnow 國際時間 time 13位或10位時間戳轉正常時間。import time def timestamp to normal time timesta...

Python學習筆記 time模組的時間戳轉換

基於python3版本的學習。time模組主要包含各種提供日期 時間功能的類和函式。該模組既提供了把日期 時間格式化為字串的功能,也提供了從字串恢復日期 時間的功能。官網教程 時間戳 格林威治時間1970年01月01日00分00秒 北京時間1970年01月01日08時00分00秒 起至現在的總秒數。...

mysql更新時間戳 Mysql中時間戳自動更新

mysql時間戳字段更新 timestamp是mysql中的時間戳字段,這個字段可以支援自動新增和更新。1.概述 在我們設計表的時候,考慮將行資料的建立時間和最後更新時間記錄下來是很好的實踐。尤其是可能需要做資料同步或者對資料新鮮度有要求的表。舉些應用場景,更新距上次更新超過2小時的行資料,或者是將...