MySQL时间设置注意事项的深入总结


Posted in MySQL onMay 06, 2021

时间真的存在吗?有观点认为,时间只是人类构想出来的一种概念,是用来衡量事物变化的标准。对于数据库来说时间伴随着数据并进。进入MySQL时间漩涡中看看。

1.时间类型的字段

MySQL时间类型字段:

MySQL时间设置注意事项的深入总结

下面的容易忽略的内容:

TIMESTAMP保存数据方式:

MySQL将TIMESTAMP值从当前时区转换为UTC进行存储,并从UTC返回到当前时区进行检索。
(这不适用于其他类型,比如DATETIME。)默认情况下,每个连接的当前时区是服务器的时间。时区可以在每个连接的基础上设置。只要时区设置保持不变,就会返回所存储的相同值。如果存储一个时间戳值,然后更改时区并检索该值,则检索到的值与存储的值不同。出现这种情况是因为没有在两个方向上使用相同的时区进行转换。当前时区可以作为time_zone系统变量的值。

MySQL时间设置注意事项的深入总结

TIMESTAMP和SQL_MODE组合

sql_mode也会影响timestamp值:

mysql> CREATE TABLE ts (
         id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
         col TIMESTAMP NOT NULL
     ) AUTO_INCREMENT = 1;

mysql> SHOW VARIABLES LIKE  '%sql_mode%';
+---------------+---------------------+
| Variable_name | Value               |
+---------------+---------------------+
| sql_mode      | STRICT_TRANS_TABLES |
+---------------+---------------------+
mysql>  INSERT INTO ts (col) VALUES ('1969-01-01 01:01:10');
ERROR 1292 (22007): Incorrect datetime value: '1969-01-01 01:01:10' for column 'col' at row 1

mysql> SET sql_mode="";
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW VARIABLES LIKE  '%sql_mode%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_mode      |       |
+---------------+-------+
mysql>  INSERT INTO ts (col) VALUES ('1969-01-01 01:01:10'),('2999-01-01 01:01:10');
Query OK, 2 rows affected, 2 warnings (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 2
mysql> show warnings;
+---------+------+----------------------------------------------+
| Level   | Code | Message                                      |
+---------+------+----------------------------------------------+
| Warning | 1264 | Out of range value for column 'col' at row 1 |
| Warning | 1264 | Out of range value for column 'col' at row 2 |
+---------+------+----------------------------------------------+

mysql> SELECT * FROM TS;
+----+---------------------+
| id | col                 |
+----+---------------------+
|  1 | 0000-00-00 00:00:00 |
|  2 | 0000-00-00 00:00:00 |
+----+---------------------+
2 rows in set (0.00 sec)

通过控制sql_mode,超出timestamp限制值还是插入进去了,但采用的是0填空方式。
对于STRICT_TRANS_TABLES, MySQL将一个无效的值转换为最接近的有效值,然后插入调整后的值。如果缺少一个值,MySQL将为列数据类型插入隐式的默认值。

2.explicit_defaults_for_timestamp时间处理机制

MySQL时间设置注意事项的深入总结

默认情况是启用。

在MySQL 8.0.22中,如果试图在声明为TIMESTAMP NOT NULL的列中插入NULL,将会被拒绝,并产生错误。

1.explicit_defaults_for_timestamp被禁用时:

  • 没有使用NULL属性显式声明的时间戳列将自动使用NOT NULL属性声明。允许为这样的列赋值为NULL,并将该列设置为当前时间戳。在MySQL 8.0.22中,如果试图在声明为TIMESTAMP NOT NULL的列中插入NULL,将会被拒绝,并产生错误。
  • 如果表中的第一列没有使用NULL属性或显式的DEFAULT或ON UPDATE属性进行声明,则会自动使用默认的CURRENT_TIMESTAMP属性和ON UPDATE CURRENT_TIMESTAMP属性进行声明。
  • TIMESTAMP 如果没有显式地使用NULL属性或显式默认属性声明,则自动声明为默认的'0000-00-00 00:00:00'(“零”时间戳)
  • 根据启用的是strict SQL模式还是NO_ZERO_DATE SQL模式,默认值“0000-00-00 00:00:00”可能无效。

2.explicit_defaults_for_timestamp被启用:

  • 不可能为TIMESTAMP指定NULL值来将其设置为当前时间戳。要指定当前时间戳,设置为CURRENT_TIMESTAMP或一个同义词,比如NOW()。
  • 没有使用not NULL属性显式声明的TIMESTAMP列将自动使用NULL属性声明并允许空值。
  • 使用NOT NULL属性声明的时间戳列不允许空值。对于为这样的列指定NULL的插入,如果启用了strict SQL模式,那么单行插入会出现错误,或者禁用了strict SQL模式的多行插入会插入'0000-00-00 00:00:00'。在任何情况下,为列赋值为NULL都不会将其设置为当前时间戳。
  • 使用NOT NULL属性显式声明且没有显式默认属性的时间戳列被视为没有默认值。对于未为此类列指定显式值的插入行,结果取决于SQL模式。如果启用了严格SQL模式,则会出现错误。如果没有启用严格的SQL模式,则使用默认隐式值'0000-00-00 00:00:00'声明该列,并出现警告。
  • timestamp类型字段 不会自动使用默认的CURRENT_TIMESTAMP属性或更新CURRENT_TIMESTAMP属性声明。这些属性必须显式指定。

MySQL时间设置注意事项的深入总结

测试:

CREATE TABLE `test1`(
id bigint not null AUTO_INCREMENT COMMENT '主键ID', 
name varchar(20) COMMENT '主键ID',
create_time TIMESTAMP  NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'cr time',
PRIMARY KEY(id)
)ENGINE=InnoDB  AUTO_INCREMENT=1 ;
SHOW VARIABLES LIKE 'explicit_defaults_for_timestamp';
SET  GLOBAL  explicit_defaults_for_timestamp=ON;
SET  GLOBAL  explicit_defaults_for_timestamp=OFF;
INSERT INTO test1(id,name,create_time) VALUES(1,'Kit',NULL);

3.mysql系统配置

系统相关事件参数包含3个:

mysql>show global variables where Variable_name like '%time_zone%' or Variable_name like 'log_timestamp%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
| log_timestamps   | UTC    |
+------------------+--------+
3 rows in set (0.00 sec)

1.system time zone:当服务器启动时,它尝试自动确定主机的时区,并使用它来设置system_time_zone系统变量。此后该值不会改变。

2.time_zone:全time_zone表示服务器当前运行的时区。初始的time_zone值为“SYSTEM”,表示服务器时区与系统时区一致。

  • 如果设置为SYSTEM, 如MySQL函数调用都会调用一个系统库来确定当前的系统时区。这个调用可能被一个全局互斥锁保护,从而导致争用。CPU使用率高问题。
  • 设置会话时区会影响时区敏感的时间值的显示和存储。这包括NOW()或CURTIME()等函数显示的值,以及存储在时间戳列中的值和从时间戳列检索到的值。时间戳列的值将从会话时区转换为UTC用于存储,从UTC转换为会话时区用于检索。
  • 会话时区设置不影响UTC_TIMESTAMP()等函数显示的值,也不影响DATE、time或DATETIME列中的值。这些数据类型的值也不存储在UTC;时区仅在从时间戳值转换时适用它们。

备注:mysql还提供时区导入到mysql系统库的方法。通过mysql_tzinfo_to_sql程序加载/usr/share/zoneinfom下的时区信息。

mysql> SELECT COUNT(*) FROM mysql.time_zone_name;
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+

##mysql_tzinfo_to_sql工具导入时区值

shell>mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
mysql> SELECT COUNT(*) FROM mysql.time_zone_name;
+----------+
| COUNT(*) |
+----------+
|     1780 |
+----------+

3.log_timestamps

这个变量控制写入错误日志的消息以及写入文件的一般查询日志和慢速查询日志消息中的时间戳的时区。

它不会影响一般查询日志的时区和慢速查询日志消息写入表(mysql。general_log mysql.slow_log)。

允许的log_timestamps值是UTC(默认值)和SYSTEM(本地系统时区)

备注:UTC一般指协调世界时。协调世界时,又称世界统一时间、世界标准时间、国际协调时间,就是UTC+8小时=中国时间

当然值 需要跟系统记录时间一致,才能更好的管理。

#设置时区,更改为东八区
SET GLOBAL time_zone = '+8:00';

MySQL时间设置注意事项的深入总结

建议:

mysql配置文件my.cnf

[mysqld]
log_timestamps=SYSTEM
default-time_zone                  = '+8:00'
mysql>show global variables where Variable_name like '%time_zone%' or Variable_name like 'log_timestamp%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| log_timestamps   | SYSTEM |
| system_time_zone | CST    |
| time_zone        | +08:00 |
+------------------+--------+

总结

从时间类型,参数,系统时区了解到,MySQL里时间应该怎样设置和使用。

特别是无特殊要求sql_mode不要轻易改动。

到此这篇关于MySQL时间设置注意事项的文章就介绍到这了,更多相关MySQL时间设置注意内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
left join、inner join、right join的区别
Apr 05 MySQL
MySQL慢查询的坑
Apr 28 MySQL
MySQL 重写查询语句的三种策略
May 10 MySQL
新手必备之MySQL msi版本下载安装图文详细教程
May 21 MySQL
如何自己动手写SQL执行引擎
Jun 02 MySQL
MySql 8.0及对应驱动包匹配的注意点说明
Jun 23 MySQL
MySQL 十大常用字符串函数详解
Jun 30 MySQL
QT连接MYSQL数据库的详细步骤
Jul 07 MySQL
MySQL 那些常见的错误设计规范,你都知道吗
Jul 16 MySQL
SQL实现LeetCode(177.第N高薪水)
Aug 04 MySQL
mysql中int(3)和int(10)的数值范围是否相同
Oct 16 MySQL
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
Apr 18 MySQL
仅用一句SQL更新整张表的涨跌幅、涨跌率的解决方案
May 06 #MySQL
MySQL创建高性能索引的全步骤
将图片保存到mysql数据库并展示在前端页面的实现代码
MySQL的join buffer原理
Apr 29 #MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 #MySQL
MySQL数据迁移相关总结
MySQL慢查询的坑
You might like
php xfocus防注入资料
2008/04/27 PHP
PHP命名空间(namespace)的使用基础及示例
2014/08/18 PHP
ThinkPHP公共配置文件与各自项目中配置文件组合的方法
2014/11/24 PHP
PHP实现Javascript中的escape及unescape函数代码分享
2015/02/10 PHP
php清除和销毁session的方法分析
2015/03/19 PHP
JavaScript中的变量声明早于赋值分析
2012/03/01 Javascript
js用Date对象处理时间实现思路及代码
2013/01/31 Javascript
页面实时更新时间的JS实例代码
2013/12/18 Javascript
jQuery弹出下拉列表插件(实现kindeditor的@功能)
2016/08/16 Javascript
Bootstrap的modal拖动效果
2016/12/25 Javascript
JS正则匹配URL网址的方法(可匹配www,http开头的一切网址)
2017/01/06 Javascript
前端常见跨域解决方案(全)
2017/09/19 Javascript
element-ui 关于获取select 的label值方法
2018/08/24 Javascript
Vue 自定义标签的src属性不能使用相对路径的解决
2019/09/17 Javascript
jQuery实现html可联动的百分比进度条
2020/03/26 jQuery
[01:29:46]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第二局
2016/02/27 DOTA
[11:12]2018DOTA2国际邀请赛寻真——绿色长城OpTic
2018/08/10 DOTA
[01:33]PWL开团时刻DAY2-开雾与反开雾
2020/10/31 DOTA
[51:20]完美世界DOTA2联赛PWL S2 Magma vs PXG 第一场 11.28
2020/12/01 DOTA
[10:05]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD 选手采访
2021/03/11 DOTA
python的常见命令注入威胁
2013/02/18 Python
Python中的yield浅析
2014/06/16 Python
pycharm显示远程图片的实现
2019/11/04 Python
如何用python处理excel表格
2020/06/09 Python
HTML5 CSS3新的WEB标准和浏览器支持
2009/07/16 HTML / CSS
Sneaker Studio乌克兰:购买运动鞋
2018/03/26 全球购物
毕业生精彩的自我评价分享
2013/10/06 职场文书
浙江文明网签名寄语
2014/01/18 职场文书
小学生考试获奖感言
2014/01/30 职场文书
初中生操行评语大全
2014/04/24 职场文书
就业协议书
2014/09/12 职场文书
工程部部长岗位职责
2015/02/12 职场文书
2015年八一建军节演讲稿
2015/03/19 职场文书
机关保密工作承诺书
2015/05/04 职场文书
vue-router中hash模式与history模式的区别
2021/06/23 Vue.js
python中if和elif的区别介绍
2021/11/07 Python