【MySQL】探究之TIMESTAMP
背景
之前有業務反饋表中start_time,end_time時間字段隨著時間的推移被自動更新,這可不是業務意愿,說的嚴重點是要出故障的。
MySQL中有DATE,DATETIME,TIMESTAMP時間類型
看看官方文檔怎么說
The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The supported range is '1000-01-01' to '9999-12-31'. The DATETIME type is used for values that contain both date and time parts. MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'. The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.
這里我們重點介紹下DATATIME和TIMESTMAP
業務反饋start_time,end_time缺失就使TIMESTAMP類型,結合TIMESTAMP的特性,我們來分析原因。
Automatic Initialization and Updating for TIMESTAMP
One TIMESTAMP column in a table can have the current timestamp as the default value for initializing the column, as the auto-update value, or both. If the column is auto-initialized, it is set to the current timestamp for inserted rows that specify no value for the column. If the column is auto-updated, it is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value.
什么意思呢?
create table gbtest_with_force_default_val
(
id bigint AUTO_INCREMENT,
t_null_1 timestamp,
t_null_2 timestamp,
t_with_not_null timestamp not null,
t_with_not_null_default timestamp not null default '2016-12-21',
primary key(id)
);
mysql> show create table gbtest_with_force_default_val;
CREATE TABLE `gbtest_with_force_default_val` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`t_null_1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`t_null_2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`t_with_not_null` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`t_with_not_null_default` timestamp NOT NULL DEFAULT '2016-12-21 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
在MySQL5.5版本中,TIMESTAMP特性
TIMESTAMP字段默認為NOT NULL,如果你在定義“t_null_1 TIMESTAMP DEFAULT NULL” 會提升“ERROR 1067 (42000): Invalid default value for 't_null_1'”。 可以指定為空 null ,“t_null_1 TIMESTAMP NULL" ,這時可以再添加語句改變默認值。
如果不做特殊說明,同一個表中會對第一個TIMESTAMP字段設置DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP屬性,第二個字段設置DEFAULT '0000-00-00 00:00:00',如果對兩個字段都顯示指定“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”,測試發現在MySQL5.6版本中并沒有該限制。
mysql> select version(); +------------------+ | version() | +------------------+ | 5.6.16.7-rc0-log | +------------------+ 1 row in set (0.00 sec) CREATE TABLE `gbtest_with_force_default_val_null` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `t_null_1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `t_null_2` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `t_with_not_null` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `t_with_not_null_default` timestamp NOT NULL DEFAULT '2016-12-21 00:00:00', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
那如何解決業務遇到的問題呢,其實很簡單,既然“DEFAULT CURRENT_TIMESTAMP”有限制,那不用好了,換成NULL DEFAULT CURRENT_TIMESTAMP去掉自動更新屬性,或者顯式的允許這兩個字段為NULL。
create table gbtest_with_force_default_val_null (
id bigint AUTO_INCREMENT,
t_null_1 timestamp NULL CURRENT_TIMESTAMP,
t_null_2 timestamp NULL DEFAULT 0,
t_with_not_null timestamp not null,
t_with_not_null_default timestamp not null default '2016-12-21', primary key(id) );
mysql> show create table gbtest_with_force_default_val_null;
CREATE TABLE `gbtest_with_force_default_val_null` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`t_null_1` timestamp NULL CURRENT_TIMESTAMP,
`t_null_2` timestamp NULL DEFAULT '0000-00-00 00:00:00',
`t_with_not_null` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`t_with_not_null_default` timestamp NOT NULL DEFAULT '2016-12-21 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
MySQL5.6版本中TIMESTAMP特性
經過學習,發現在5.6版中中多了一個叫“explicit_defaults_for_timestamp”的系統變量,但默認是OFF的,但是也可以支持一個表中多個字段的同時更新。
mysql> show variables like '%explicit_defaults_for_timestamp%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | explicit_defaults_for_timestamp | OFF | +---------------------------------+-------+ 1 row in set (0.00 sec)
那將這個參數打開會有什么不同?
mysql> set @@global.explicit_defaults_for_timestamp=ON;
ERROR 1238 (HY000): Variable 'explicit_defaults_for_timestamp' is a read only variable
該參數并不支持動態修改!!!
create table gbtest_with_noforce(
id bigint AUTO_INCREMENT,
t_null_1 timestamp,
t_null_2 timestamp,
t_with_not_null timestamp not null,
t_with_not_null_default timestamp not null default '2016-12-21',
primary key(id)
);
CREATE TABLE `gbtest_with_noforce` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`t_null_1` TIMESTAMP NULL DEFAULT NULL,
`t_null_2` TIMESTAMP NULL DEFAULT NULL,
`t_with_not_null` TIMESTAMP NOT NULL,
`t_with_not_null_default` TIMESTAMP NOT NULL DEFAULT '2016-12-21 00:00:00',
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8
;
發現如下改變:
默認參數為NULL
并不會自動添加DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP等屬性
結論
那考慮的版本的兼容性,測試發現,在5,5版本中按默認屬性創建的表,在5.6版本中遷移是沒有任何問題的,是完全兼容的。這說明,使用Mysql5.6以后的版本,應立即將explicit_defaults_for_timestamp參數設置為True,并及時反饋開發TIMESTAMP的行為。
總結
以上是生活随笔為你收集整理的【MySQL】探究之TIMESTAMP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FORMAT格式
- 下一篇: 服务器定时重启计划任务