mysql中datetime和timestamp的区别

2020-03-18  本文已影响0人  PENG先森_晓宇

时间戳

时间不分东西南北、在地球的每一个角落,每一个国家都是一样的。

在中国时间过去5秒钟,美国同样也是过去了5秒钟,在地球的任何一个角度都是过去了5秒钟,时间戳就是相对于格林威治时间1970年01月01日00时00分00秒起至现在过去的总秒数,这个总秒数在世界上的任何地方都是相同,也就是说时间戳在世界上的任何地方都是相同的,时间戳没有时区的概念

时间戳强调的是过去时,相对1970年01月01日00时00分00秒起过去了多长时间。

时区

我们知道了在任何地方时间戳都是相同的。当我们问现在是什么时候,我们总不能说相对于1970年01月01日00时00分00秒过去了n秒,太模糊了,于是就有了时间的定义,我们可以说现在是2020年03月15号23点53分,方便我们记忆和理解。

时间和实践戳想比较,时间强调的是现在时,现在是何年何月何日,何时何分何妙,而时间戳强调的是过去时,过去了多少秒。

通常我们将每天太阳在最高点的时候定义为12点,而由于地球的自转,导致每个地方太阳出现在最高点的时间又不尽相同,为了统一时间(太阳最高点为12点)于是就出现了时区的概念。

我们中国处于东+8区,美国处于西-5区

最后总结一个表达式:实践戳+时区=当前时间

mysql的时区

查看mysql的时区

mysql> show variables like '%time_zone%';

+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+

可以看到Variable_name有俩个变量,system_time_zone是指系统默认的时区,time_zone指当前时区
可以看到系统默认时区为CST,而当前时区是system,也就是当前时区为系统默认时区,也就是当前时区为CST。

那么CST时区是什么呢?

修改mysql的时区

有俩种方式

set global time_zone = '+8:00'; ##修改mysql全局时区为北京时间,即我们所在的东8区
set time_zone = '+8:00'; ##修改当前会话时区
flush privileges; #立即生效
##在[mysqld]区域中加上
default-time_zone = '+8:00'
## 重启mysql
systemctl  restart mysql

连接mysql客户端的时区

mysql有时区,连接mysql的客户端同样也有时区的问题,例如php,java,我们以php为例介绍

echo date_default_timezone_get()

在中国默认的时区是RPC,也就是+8:00。

date_default_timezone_set('Europe/Paris');

php可用的时区,请看这篇文章。

操作系统时区

操作系统也是有时区的,输入date -R查看操作系统时区。看到后面是+0800,也就是代表北京时间。

[root@m1 ~]# date -R
Tue, 17 Mar 2020 11:41:46 +0800

操作系统时区影响的是依附操作系统获取时间的操作,例如在shell脚本中获取时间-time=$(date "+%Y%m%d-%H%M%S")。
还有我们最常用的crontab定时任务,crontab中的时分秒肯定是依附于操作系统时区的。
以下俩点需要注意系统时区问题。

datetime和timestamp的区别

类型 占据字节 表现形式
datetime 8字节 yyyy-mm-dd hh:mm:ss
timestamp 4字节 yyyy-mm-dd hh:mm:ss

由于datetime和timestamp占据的字节不一样,以至于表示的存储范围也肯定不一样。

类型 表现范围
datetime 1000-01-01 00:00:00.000000 - 9999-12-31 23:59:59.999999
timestamp 1970-01-01 00:00:01.000000 to 2038-01-19 03:14:07.999999

通过上面的分析我们知道了

类型 时区影响
datetime 没有影响
timestamp 有影响

通过上面的分析,我们知道了mysql的时区大概作用于以下俩点

1. timestamp类型的数据,mysql实际存储的是时间戳,而表现形式却是时间,时间戳转化为时间肯定需要时区的转化。时间戳+时区=时间。
2. mysql中的函数FROM_UNIXTIME()(把时间戳转化为时间)和UNIX_TIMESTANMP()(把时间转化为时间戳)也会根据mysql时区进行的转换

mysql存储时间时到底选择datetime,timestamp还是int类型?

datetime和timestamp比大小

比如获取2020-03-01以后新注册的用户

select * from users where created_at > `2020-03-01`

比如获取2020年以后新注册的用户

select * from users where created_at >= `2020`
### 或者
select * from users where year(created_at) > '2020'

一次线上迁库发生的事故

我们的数据库是使用timestamp类型来存储时间的,当前的数据库的时区为+8:00。

有一次我们需要迁库,迁移的那个库没太注意时区,迁移过去之后发现所有用户的每天获取的积分都不对了,获取积分的时间都少了8个小时。

最后反应过来可能是新的数据库的时区与老数据库不一致,查看后发现新数据库的时区果然不是+8:00,时区修改完之后就和之前的时间对上了。

所以存储时间的类型是很重要的,选择时需要考虑清楚。

总结

如果数据库中有timestamp类型的字段,mysql数据库不管是迁库,还是集群,都一定要保证时区的相同。如果mysql集群中的数据库时区不一致,timestamp的字段将会造成数据不一致的情况发生。在迁移库或者搭建集群时一定检查时区,保证时区的相同

中国时区默认是+8,所以不管是单节点mysql,还是mysql集群,我们第一件事就是应该将当前时区time_zone设置为+8:00

上一篇 下一篇

猜你喜欢

热点阅读