细说MySQL的时间戳(Timestamp)类型

细说MySQL的时间戳(Timestamp)类型转载生产环境中部署着各种版本的 MySQL 包括 MySQL5 5 5 6 5 7 三个大版本和 N 个小版本 由于 MySQL 在向上兼容性较差 导致相同 SQL 在不同版本上表现各异 下面从几个方面来详细介绍时间戳数据类型 nbsp 时间戳数据存取 nbsp nbsp 在 MySQL 上述三个大版本中 默认时间戳 Timestamp 类型的取值范围为 1970 01 0100 00 01 UTC nbsp 至 2038 01 1903 14

转载

生产环境中部署着各种版本的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_XXX获取已创建表的建表语句。

 

时间戳字段在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.’,能更好地存放各时间段的数据。

 

 

时间戳类型使用建议

  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线下测试版本和线上生产版本保持一致。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228969.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午5:46
下一篇 2026年3月16日 下午5:46


相关推荐

  • MPLS TE可靠性及其案例

    MPLS TE可靠性及其案例

    2021年4月15日
    154
  • 解决gitignore不起作用

    解决gitignore不起作用gitignore 中已经标明忽略的文件目录下的文件 gitpush 的时候还会出现在 push 的目录中 原因是因为在 git 忽略目录中 新建的文件在 git 中会有缓存 修改的文件已经被纳入了版本管理中 就算是在 gitignore 中声明了忽略路径也是不起作用的 这时候我们就应该先把本地缓存删除 然后再进行 git 的 push 这样就不会出现忽略的文件了 git 清除本地缓存命令如下 gitr

    2026年3月26日
    2
  • tar 打包的时候如何去掉目录前缀

    tar 打包的时候如何去掉目录前缀文章转载自:freefly的博客,对原作者表示感谢。问题:tarczfxx.tgz/xxx/xxx/A然后希望xx.tgz或xx.tar.gz里面就直接A这个目录不希望加前导xxx/xxx,我知道可以先cp这个目录到同一个目录再打包,不过想知道可以不可以不用另外cp到同一个目录 答案1:使用-C指定相对路径,如:tarczfx

    2022年5月6日
    83
  • Cursor 写文档与写代码怎么协作:真正决定质量的不是提示词,而是流程

    Cursor 写文档与写代码怎么协作:真正决定质量的不是提示词,而是流程

    2026年3月16日
    2
  • 敏捷软件开发 – 原则、模式与实践

    敏捷软件开发 – 原则、模式与实践起源 敏捷软件开发 原则 模式与实践 是我接触到的第一本系统介绍软件设计的书籍 深刻影响了个人的软件开发习惯 它并不难懂 我一直推荐给身边的各个层次的程序员学习 可对于一本接近 500 页的图书 很多人还是望而却步 一直都想写个关于这本书的速读 使更多的人了解它 但是最近又重新学习了一遍发现它之所以有价值不仅仅在于书中总结的原则和模式 更在于它提供的如何运用这些原则 模式的实践例子 忽略了大量

    2026年3月19日
    2
  • 电商后台管理系统(一)

    电商后台管理系统(一)后台管理系统git地址:https://gitee.com/kk23851一.项目大体架构二.用户登录用户登录页面思路:用Element表单验证完成以后,把数据存储到本地用户登录代码位置如图:三.用户管理用户列表页面绘制用户列表基本结构,请求用户列表数据,将用户列表数据展示,实现用户列表分页,实现搜索功能,实现添加用户,修改用户信息,删除用户,分配权限用户管理代码位置如图:四.权限管理权限管理有俩个板块分别是角色列表和权限列表,用到的技术无非就是element-ui,所

    2022年6月10日
    50

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号