龙空技术网

MySQL的时间戳2038年问题,在Linux系统上使用mysql8模拟下

flyiot 2036

前言:

现时兄弟们对“debian8mysql”大体比较关怀,大家都想要剖析一些“debian8mysql”的相关资讯。那么小编在网络上搜集了一些有关“debian8mysql””的相关资讯,希望兄弟们能喜欢,你们一起来学习一下吧!

目录前言1,关于MySQL时间戳的2038年BUG2,使用Docker创建MySQL 模拟下3,总结下1,关于MySQL时间戳的2038年BUG

当 timestamp 存储的时间大于 ‘2038-01-19 03:14:07’ UTC,mysql就会报错,

因为这是 mysql自身的问题,也就是说 timestamp是有上限的,超过了,自然会报错。

timestamp的时间范围是:‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC ,自动时区转化,实际存储毫秒数,4字节存储datetime的时间范围:‘1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’ ,不支持时区,8字节存储

但是真的到了2038年会怎样呢?

2,在Linux上,使用Docker创建MySQL 模拟下

Mac 系统不让修改到2038年1月1日以后,估计会有BUG,直接变砖。找了个Linux上进行修改。

在默认的Linux 系统上开启了时间同步需要停止下,然后直接设置成2038年2月1日。

创建表之后再修改时间,在linux 系统上进行修改。

不是进入docker 环境中修改。

sudo systemctl stop systemd-timesyncdsudo date -s 20380202[sudo] test 的密码: 2038年 02月 02日 星期二 00:00:00 CST

这里需要使用最新的myslq 版本。

使用5.7 更改日期,直接异常了:

起码DBA是要在这之前升级到新版本,需要忙活一阵子了。

2038-02-01T16:00:14.626767Z 6 [Warning] Iteration 1: Current time obtained from system is greater than 20382038-02-01T16:00:14.626778Z 6 [Warning] Iteration 2: Current time obtained from system is greater than 20382038-02-01T16:00:14.626786Z 6 [Warning] Iteration 3: Current time obtained from system is greater than 20382038-02-01T16:00:14.626794Z 6 [Warning] Iteration 4: Current time obtained from system is greater than 20382038-02-01T16:00:14.626801Z 6 [Warning] Iteration 5: Current time obtained from system is greater than 20382038-02-01T16:00:14.626809Z 6 [ERROR] This MySQL server doesn't support dates later than 20382038-02-01T16:00:14.627757Z 0 [Note] Giving 2 client threads a chance to die gracefully2038-02-01T16:00:14.627821Z 0 [Note] Shutting down slave threads2038-02-01T16:00:16.627925Z 0 [Note] Forcefully disconnecting 2 remaining clients

启动最新的mysql 8 :

docker run -itd -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root \  -v /data/mysql:/var/lib/mysql --name mysql mysql:debian# 设置密码root # 设置存储文件在/data/mysql 目录才可以启动成功。

创建数据库和表:

CREATE DATABASE demo DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE TABLE `test_time` (  `id` bigint(16) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',  `time1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='测试时间表';

然后插入下,确实插入有问题了。

mysql>   insert into sys_test(id,time1) values (1, now());ERROR 1292 (22007): Incorrect datetime value: '2038-02-01 16:00:45' for column 'time1' at row 1mysql> 

但是进行查询的时候:

mysql> SELECT FROM_UNIXTIME ( UNIX_TIMESTAMP() )    -> ;+------------------------------------+| FROM_UNIXTIME ( UNIX_TIMESTAMP() ) |+------------------------------------+| 2038-02-01 16:05:20                |+------------------------------------+1 row in set (0.00 sec)mysql> select UNIX_TIMESTAMP();+------------------+| UNIX_TIMESTAMP() |+------------------+|       2148653589 |+------------------+1 row in set (0.00 sec)mysql> SELECT FROM_UNIXTIME ( 2147483647 )    -> ;+------------------------------+| FROM_UNIXTIME ( 2147483647 ) |+------------------------------+| 2038-01-19 03:14:07          |+------------------------------+1 row in set (0.00 sec)

模拟的方式,首先使用最新的mysql 8 ,然后创建库和表,再插入数据。

重启 mysql 8 ,首先只有mysql 8 最新的是可以启动成功。其他的版本没有实验。

然而并没有出现查询出 1970 年的情况,没有溢出,说明数据库已经对时间戳进行升级,支持 2147483647 以上的数据了。

但是要是对数据库进行映射 还是需要使用 long 型比较稳妥。

或者数据库直接换成 datetime 类型即可。

3,总结

所以在设计 mysql 数据表的时候还是要使用 datetime 比较好。

不要使用时间戳字段,虽然还有16年,以后用啥数据库都不知道了。

但是保险起见还是一次到位好,再有datetime 更直观,时间戳看的费劲。

还需要转换,使用不方便。

还是那句老话,还是踏踏实实的使用 datetime 时间戳进行存储吧。

标签: #debian8mysql