• 【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的行为。

  • 相关阅读:
    javascript定时器,取消定时器,及js定时器优化方法
    Systen,IO
    批量地理位置解析
    数据库分区分表(sql、mysql)
    数据库还原的多种方式
    js前端文件收集(一)
    NPOI解决由于excel删除数据导致空行读取问题
    echarts2.0tooltip边框限制导致tooltip显示不全解决办法
    数据库备份通用脚本
    echarts 用marlkline画线 同时配置中含有datazoom,怎么设置markline
  • 原文地址:https://www.cnblogs.com/zhiqian-ali/p/5225869.html
Copyright © 2020-2023  润新知