mysql数据库常用的时间类型有timestamp和datetime,两者主要区别是占用存储空间长度不一致、可存储的时间也有限制,但针对不同版本下,timestamp字段类型的设置需要慎重,因为不注意的可能会被“坑死”。

一、TIMESTAMP和DATETIME字段类型对比

字段类型 存储长度 时间范围 备注
timestamp 4字节 '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC  
datetime 8字节(5.7占5字节) '1000-01-01 00:00:00' to '9999-12-31 23:59:59'  

1.timestamp注意事项

(1)5.7版本之前,没有explicit_defaults_for_timestamp 参数(5.7默认开启,timestamp不会设置default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP属性),timestamp字段默认存在default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP属性,默认值针对的主要是以下函数产生的时间

These are CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, and LOCALTIMESTAMP().

(2)mysql的timestamp值自动从当前时区转换到utc时区存储,并且自动从utc时区转换为当前系统时区检索返回

官方参考文档:https://dev.mysql.com/doc/refman/5.7/en/datetime.html

MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. 
(This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time.

2.datetime注意事项:

在mysql5.7之后,datetime字段也可以指定默认值,并且格式和timestamp一样

CREATE TABLE t1 (
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

DEFAULT or DEFAULT '2000-01-01 00:00:00'

二、数据库时区参数

1.system_time_zone

  数据库实例启动,从my.cnf配置参数timezone=timezone_name获取,若my.cnf未设置则从操作系统获取环境变量TZ获取
2.time_zone

  数据库当前实际使用的时区,默认为system,即系统时区,其设置可以通过set global time_zone=''设置,其中参数值有以下三种形式:'SYSTEM' 、'+10:00' 、'Europe/Helsinki'

Linux时区知识扩展:
Linux将时钟分为系统时钟(System Clock)和硬件(Real Time Clock,简称RTC)时钟两种。系统时间是指当前Linux Kernel中的时钟,
而硬件时钟则是主板上由电池供电的那个主板硬件时钟,这个时钟可以在BIOS的"Standard BIOS Feture"项中进行设置。
系统时钟:
所有操作系统命令、函数依赖的时钟,独立于硬件时钟运行,可通过date设置
设置系统时间:date -s "2017-08-22 22:58:00"
查看时区:date -R 硬件时钟:
Linux启动从系统配置获取
查看硬件时钟:clock --show 、 hwclock --show
设置硬件时钟:hwclock/clock --set --date="月/日/年 时:分:秒"
系统时钟同步到硬件:/sbin/clock -w
硬件时钟同步到系统:/sbin/clock -s 时区设置:
修改/etc/sysconfig/clock
ZONE=Asia/Shanghai
rm /etc/localtime
链接到上海时区文件
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
执行完上述过程后,重启机器,即可看到时区已经更改。

、实际使用实例

1.不同版本下timestamp和datetime使用实例

(1)测试timestamp和datetime创建带默认值的表
同时执行创建带默认值的SQL语句,发现5.6(不含5.6)之前版本datetime不支持带DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

CREATE TABLE test (
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); 5.0.67版本
ERROR (): Invalid default value for 'dt' 5.5.20版本
ERROR (): Invalid default value for 'dt' 5.6.22版本
Query OK, rows affected (0.02 sec) 5.7.18版本
Query OK, rows affected (0.00 sec)

(2)测试timestamp和datetime创建表结构类型

不指定默认值的情况下创建表结构,发现5.6(不含5.6)timestamp默认值是CURRENT_TIMESTAMP并且随着记录更新而更新

CREATE TABLE test01 (
ts TIMESTAMP ,
dt DATETIME
); 5.0.67版本
CREATE TABLE `test01` (
`ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`dt` datetime default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 5.5.20版本
CREATE TABLE `test01` (
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 5.6.22版本
CREATE TABLE `test01` (
`ts` timestamp NULL DEFAULT NULL,
`dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 5.7.18版本
CREATE TABLE `test01` (
`ts` timestamp NULL DEFAULT NULL,
`dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

(3)、测试timestamp和datetime类型mysqldump导出导入影响

测试结论为,timestamp数据类型的记录导出会以utc时间格式导出,导入库中自动由UTC格式转为系统默认时区,所以看到导出文件timestamp内容时间戳和实际存储的不相符。

如果需要看到和导入与实际相符的时间戳,需要加入参数--tz-utc=false用于禁止timestamp时区转换,默认是开启的,即导出文件中开头设置的/*!40103 SET TIME_ZONE='+00:00' */;

系统默认是cst时区,数据库参数设置也是CST和SYSTEM,根据系统时间插入数据:

| system_time_zone | CST    |
| time_zone              | SYSTEM |

insert into test01 values(sysdate(),sysdate());

5.0.67版本
select * from test01;
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+ 5.5.20版本
select * from test01;
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+ 5.6.22版本
select * from test01;
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+ 5.7.18版本
select * from test01;
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+

然后将数据库表test01表利用mysqldump导出

mysqldump dbtest --tables test01  >test01.sql
5.0.67版本
-- MySQL dump 10.11
--
-- Host: localhost Database: dbtest
-- ------------------------------------------------------
-- Server version 5.0.67-percona-highperf-log
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `test01` (
`ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`dt` datetime default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-12 06:15:19','2018-01-12 14:15:19');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on -- ::
5.5.20版本
-- MySQL dump 10.13 Distrib 5.5., for Linux (x86_64)
--
-- Host: localhost Database: dbtest
-- ------------------------------------------------------
-- Server version 5.5.20-rel24.1-log /*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test01` (
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-12 06:15:27','2018-01-12 14:15:27');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on -- ::
5.6.22版本
-- MySQL dump 10.13 Distrib 5.6.-71.0, for Linux (x86_64)
--
-- Host: localhost Database: dbtest
-- ------------------------------------------------------
-- Server version 5.6.22-71.0-log
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test01` (
`ts` timestamp NULL DEFAULT NULL,
`dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-07 12:13:22','2018-01-07 20:13:22');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on -- ::
5.7.18版本
-- MySQL dump 10.13 Distrib 5.7.-, for Linux (x86_64)
--
-- Host: localhost Database: dbtest
-- ------------------------------------------------------
-- Server version 5.7.18-15-log /*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
--
-- Table structure for table `test01`
--
DROP TABLE IF EXISTS `test01`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test01` (
`ts` timestamp NULL DEFAULT NULL,
`dt` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `test01`
--
LOCK TABLES `test01` WRITE;
/*!40000 ALTER TABLE `test01` DISABLE KEYS */;
INSERT INTO `test01` VALUES ('2018-01-07 12:13:20','2018-01-07 20:13:20');
/*!40000 ALTER TABLE `test01` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-- Dump completed on -- ::

删除test01表,并用mysqldump导出文件还原

mysql -D dbtest -e "drop tables test01"
mysql -D dbtest <test01.sql
select * from test01; 5.0.67版本
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+
5.5.20版本
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+
5.6.22版本
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+
5.7.18版本
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| -- :: | -- :: |
+---------------------+---------------------+

(4)ON UPDATE CURRENT_TIMESTAMP属性影响

如果包含ON UPDATE CURRENT_TIMESTAMP属性,则如果对表记录更新,此记录对应的timestamp类型记录也会更新

ts字段是timestamp类型且含有on update current_timestamp属性,dt字段是datetime类型且不含on update current_timestamp属性
更新前:
mysql -D dbtest -e "select * from test01;"
+---------------------+---------------------+------+
| ts | dt | id |
+---------------------+---------------------+------+
| -- :: | -- :: | NULL |
+---------------------+---------------------+------+
更新:
mysql -D dbtest -e "update test01 set id=1 where id is null"
更新后:
mysql -D dbtest -e "select * from test01;"
Logging to file '/home/mysql/query.log'
+---------------------+---------------------+------+
| ts | dt | id |
+---------------------+---------------------+------+
| -- :: | -- :: | |
+---------------------+---------------------+------+

2.不同版本下mysqldump结束时间分析

使用mysqldump备份的同仁都可能会注意到,正常备份结束的话,在文件结尾会有一条成功结束的表示,即 :-- Dump completed on 2018-01-12  6:22:25。

这个在mysql5.0后可以通过一些参数控制,例如可以加参数--comments=false来禁止添加comments信息,即所有--开头的comment会不记录在备份文件中,也可以增加--dump-date=false来禁止时间戳添加,即只包含-- Dump completed。

但特别需要注意的是,此时间戳的由来在mysqldump 10.11版本(mysql5.0.x版本对应MySQL dump 10.11, 含10.11版本)记录的是UTC时区时间戳,而在mysqldump 10.12版本之后(mysql 5.5对应的版本是MySQL dump 10.13,含10.13)记录的是系统当前时区时间戳。

所以大家看到的是mysqldump 10.11备份结束的时间总是比系统当前时间提前8小时,例如mysql5.0系统当前是CST时区:2018-01-12  14:22:25   而备份文件结束时间戳是-- Dump completed on 2018-01-12  6:22:25。这个只是记录的时间戳不同,不影响最终的数据记录时间。

源码片段如下:

./client/mysqldump.c

#define DUMP_VERSION "10.13"

static void write_footer(FILE *sql_file)
{
if (opt_xml)
{
fputs("</mysqldump>\n", sql_file);
check_io(sql_file);
}
else if (!opt_compact)
{
if (opt_tz_utc)
fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n"); fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n");
if (!path)
{
fprintf(md_result_file,"\
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
}
if (opt_set_charset)
fprintf(sql_file,
"/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
"/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
"/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
fprintf(sql_file,
"/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n");
fputs("\n", sql_file); if (opt_dump_date)
{
char time_str[];
get_date(time_str, GETDATE_DATE_TIME, 0);
print_comment(sql_file, 0, "-- Dump completed on %s\n"
, time_str);
}
else
print_comment(sql_file, , "-- Dump completed\n"); check_io(sql_file);
}
} /* write_footer */

get_date()函数是核心,那么其源码./mysys/mf_getdate.c如下:

MySQL案例之Timestamp和Datetime的更多相关文章

  1. MySQL中有关TIMESTAMP和DATETIME的总结

    一.MySQL中如何表示当前时间? 其实,表达方式还是蛮多的,汇总如下: CURRENT_TIMESTAMP CURRENT_TIMESTAMP() NOW() LOCALTIME LOCALTIME ...

  2. MySQL中有关TIMESTAMP和DATETIME的对比

    TIMESTAMP和DATETIME的相同点: 1> 两者都可用来表示YYYY-MM-DD HH:MM:SS[.fraction]类型的日期. TIMESTAMP和DATETIME的不同点: 1 ...

  3. MySQL时间格式TIMESTAMP和DATETIME的区别

    时区,timestamp会跟随设置的时区变化而变化,而datetime保存的是绝对值不会变化 自动更新,insert.update数据时,可以设置timestamp列自动以当前时间(CURRENT_T ...

  4. Mysql存储日期类型用int、timestamp还是datetime?

    通常存储时间用datetime类型,现在很多系统也用int存储时间,它们有什么区别?个人更喜欢使用int这样对于日期计算时比较好哦,下面我们一起来看到底那种会好些. int ().4个字节存储,INT ...

  5. MYSQL时间类别总结: TIMESTAMP、DATETIME、DATE、TIME、YEAR

    总结背景: 对于MYSQL数据库日期类型或多有了解, 但并很清晰其中一些规则. 基本都是面向浏览器编码, 这实质上也是一种方式.  但期间遇到两个问题: 时常遇到建表中出现多个datetime或者ti ...

  6. mysql中的时间类型datetime,date,time,year,timestamp小知识点

    1.datetime,date,time,year四个类型的值,可以手动输入,也可以调用函数获得值 ① 手动输入,格式如下: datetime "2016-6-22 14:09:30&quo ...

  7. 【记录】mysql中建表utf8和utf8mb4区别?timestamp和datetime区别?

    mysql中建表utf8和utf8mb4区别? 1:utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符,也就是 Unicode 中的基本多文本平面 2:要在 Mysql 中 ...

  8. [MySQL] timestamp和datetime的区别和大坑

    1.timestamp占用4个字节;datetime占用8个字节2.timestamp范围1970-01-01 00:00:01.000000 到 2038-01-19 03:14:07.999999 ...

  9. TIMESTAMP和DATETIME的区别

    TIMESTAMP和DATETIME的区别 1. 存储空间不同 a) TIMESTAMP占用4个字节 b) DATETIME占用8个字节 2. 受时区影响 c) TIMESTAMP实际记录的是1970 ...

随机推荐

  1. nginx实现多语言跳转不同的url

    nginx实现多语言跳转不同的url server { listen 80; server_name www.text.com; location / { if ($http_accept_langu ...

  2. J15W-J45W铜制截止阀厂家,J15W-J45W铜制截止阀价格 - 专题栏目 - 无极资讯网

    无极资讯网 首页 最新资讯 最新图集 最新标签   搜索 J15W-J45W铜制截止阀 无极资讯网精心为您挑选了(J15W-J45W铜制截止阀)信息,其中包含了(J15W-J45W铜制截止阀)厂家,( ...

  3. vscode安装golang插件失败问题

    vscode安装golang插件失败问题 dlv go-outline go-symbols gocode-gomod gocode 代码补全 godef 代码跳转 golint gopkgs gor ...

  4. 《The Python Standard Library》——http模块阅读笔记3

    http.cookies — HTTP state management http.cookies模块定义了一系列类来抽象cookies这个概念,一个HTTP状态管理机制.该模块支持string-on ...

  5. 2019美国大学生数学建模竞赛B题(思路)

    建模比赛已经过去三天了,但留校的十多天里,自己的收获与感受依然长存于心.下面的大致流程,很多并没有细化,下面很多情况都是在假设下进行的,比如假设飞机能够来回运送药品,运货无人机就只运货,在最大视距下侦 ...

  6. mac下 mysql 插入中文乱码解决

    搞了好几个小时,终于搞定了 乱码根本原因还是编码方式不同造成的,只要编码方式统一就没问题 1. 进入 mysql 命令行, 用 show variables like 'character_set_% ...

  7. c++ 网络编程(三) LINUX/windows 进程间的通信原理与实现代码 基于多进程的服务端实现

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9613027.html 锲子:进程与线程是什么,他们的区别在哪里: 1 进程概念 进程是程序的一 ...

  8. 【Lua】CJSON的安装

    Lua CJSON 是 Lua 语言提供高性能的 JSON 解析器和编码器,其性能比纯 Lua 库要高 10 到 20 倍.Lua CJSON 完全支持 UTF-8 ,无需依赖其他非 Lua/LuaJ ...

  9. word-wrap和word-break的区别吗?

    word-wrap: css的 word-wrap 属性用来标明是否允许浏览器在单词内进行断句,这是为了防止当一个字符串太长而找不到它的自然断句点时产生溢出现象. word-break: css的 w ...

  10. SpringMVC Controller层的单元测试

    Getting Ready 测试相关Maven dependency如下: <dependency> <groupId>org.springframework</grou ...