【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特性

  1. 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" ,这时可以再添加语句改变默认值。
  2. 如果不做特殊说明,同一个表中会对第一个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
;

发现如下改变:

  1. 默认参数为NULL
  2. 并不会自动添加DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP等属性

结论

那考虑的版本的兼容性,测试发现,在5,5版本中按默认属性创建的表,在5.6版本中迁移是没有任何问题的,是完全兼容的。这说明,使用Mysql5.6以后的版本,应立即将explicit_defaults_for_timestamp参数设置为True,并及时反馈开发TIMESTAMP的行为。

时间: 2024-10-14 05:03:53

【MySQL】探究之TIMESTAMP的相关文章

MySQL中有关TIMESTAMP和DATETIME的总结

原文:MySQL中有关TIMESTAMP和DATETIME的总结 一.MySQL中如何表示当前时间? 其实,表达方式还是蛮多的,汇总如下: CURRENT_TIMESTAMP CURRENT_TIMESTAMP() NOW() LOCALTIME LOCALTIME() LOCALTIMESTAMP LOCALTIMESTAMP() 二.关于TIMESTAMP和DATETIME的比较 一个完整的日期格式如下:YYYY-MM-DD HH:MM:SS[.fraction],它可分为两部分:date部

mysql多个TimeStamp设置(转)

timestamp设置默认值是Default CURRENT_TIMESTAMP timestamp设置随着表变化而自动更新是ON UPDATE CURRENT_TIMESTAMP 但是由于 一个表中至多只能有一个字段设置CURRENT_TIMESTAMP 两行设置DEFAULT CURRENT_TIMESTAMP是不行的. 还有一点要注意 CREATE TABLE `device` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `toid`

jackson/fastjson、mybatis、mysql date/datatime/timestamp、java Date/Timestamp关系详解

jackson/fastjson序列化/反序列化: 默认情况下,jackson/fastjson将java Date/Timestamp类型序列化为时间戳,也就是1970年1月1日0点以来的毫秒数.如果要显示为用户友好表示: Jackson 可以: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); objectMapper.setDateFormat(sdf)或者:@JsonFormat(locale

mysql 查询时间戳(TIMESTAMP)转成常用可读时间格式

from_unixtime()是MySQL里的时间函数 date为需要处理的参数(该参数是Unix 时间戳),可以是字段名,也可以直接是Unix 时间戳字符串 后面的 '%Y%m%d' 主要是将返回值格式化 例如: mysql>SELECT FROM_UNIXTIME( 1249488000, '%Y%m%d' ) ->20071120 mysql>SELECT FROM_UNIXTIME( 1249488000, '%Y年%m月%d' ) ->2007年11月20 UNIX_TI

mysql 多个timestamp 错误:there can be only one TIMESTAMP column with CURRENT_TIMESTAMP

mysql 5.6.5以下的版本不支持多个timestamp同时设为default current_timestamp 替代方式是使用trigger CREATE TABLE `example` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `lastUpdated` DATETIME NOT NULL, PRIMARY KEY (`

MySQL `explicit_defaults_for_timestamp` 与 TIMESTAMP

考察下面的 SQL 脚本: CREATE TABLE test1( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, data VARCHAR(20), ts1 TIMESTAMP NOT NULL, createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_T

mysql探究之null与not null

相信很多用了MySQL很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 1.我字段类型是not null,为什么我可以插入空值 2.为毛not null的效率比null高 3.判断字段不为空的时候,到底要  select * from table where column <> '' 还是要用 select * from table where column is not null 呢. 带着上面几个疑问,我们来深入研究一下null 和 not null 到底有什么不一样. 首

oracle、mysql时区设置对timestamp的不同影响

因最近国际去Oracle上MySQL,这就不可避免的涉及到时区和timestamp问题.做一下实验,总结一下. Oracle 首先看下oracle concepts对timestamp的定义: The TIMESTAMP data type is an extension of the DATE data type. It stores fractional seconds in addition to the information stored in the DATE data type.

mysql之TIMESTAMP(时间戳)用法详解

一.TIMESTAMP的变体 TIMESTAMP时间戳在创建的时候可以有多重不同的特性,如: 1.在创建新记录和修改现有记录的时候都对这个数据列刷新: ? 1 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 2.在创建新记录的时候把这个字段设置为当前时间,但以后修改时,不再刷新它: ? 1 TIMESTAMP DEFAULT CURRENT_TIMESTAMP 3.在创建新记录的时候把这个字段设置为0,以后修改时刷新