13 mysql date/time/datetime/year 的数据存储

前言

这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 

探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 

本文主要 的相关内容是 datetime/date/time/year 类类型的相关数据的存储  

这部分数据 客户端 和 服务器这边的交互 主要是以字符串的形式交互 

服务器这边的存储 将日期编码为 整形进行存储 

 

最近碰到了一个这样的一个问题

主要是在一个 增量同步的地方, 增量同步 tableA, 增量查询字段为 create_time, 类型为 datetime

然后 业务组件中 select max(create_time) from tableA 中查询到的最大时间 居然比实际的最大时间 多了 13 个小时, 呵呵

然后 这就导致了 增量同步存在问题

下一次增量同步的时候, 将 增量同步的最大值更新为了 13个小时以后, 这样 根据这个时间去做增量查询 接下来的 13 个小时的任务执行 都查询不到 需要增量同步的记录

然后 最终是发现 服务器的 default-time-zone 被调整了, 重置一下 default-time-zone 即可 

我这里 mysql 服务器版本为 5.7.31

 

 

mysql 中 datetime 的数据交互

创建表 以及插入测试数据

CREATE TABLE `tz_test` (`id` int(11) NOT NULL AUTO_INCREMENT,`field1` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;INSERT INTO `test`.`tz_test`(`id`, `field1`) VALUES (1, '2023-04-24 16:25:40');

 

测试脚本如下 

package com.hx.test07;/*** Test06MysqlTimezone** @author Jerry.X.He* @version 1.0* @date 2023/4/24 16:26*/
public class Test06MysqlTimezone {// Test06MysqlTimezonepublic static void main(String[] args) {String url = "jdbc:mysql://10.60.50.16:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&autoReconnectForPools=true&useSSL=false";String username = "root";String password = "root";JdbcTemplate jdbcTemplate = Test14GenExpertSql.getMysqlJdbcTemplate(url, username, password);String sql = " select * from tz_test; ";List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);int x = 0;}}

 

抓包拿到 mysql 响应解析如下 

可见这里 wireshark 解析貌似是存在问题的, 前两个 packet 对应的是 字段列表的元数据 

第三个 packet 是具体的数据, 包含了 packetLength, packetNumber, 字段id, 字段field1

第四个 packet 是 eof 包 

6e2fe246a7f54cdfbf94b9c80d88cbe3.png

 

业务查询从服务器拿到的数据部分的如下, 可以看到的是 和上面一致

可以看到的是 datetime 的交互是通过字符串的形式交互的, 因此 存取的时候的转换都是服务器自己处理的

第一个字节 01 表示 id 数据长度 1 

第二个字节 31 表示 id 为 1

第三个字节 13 表示 field1 数据长度 19

剩余十九个字节为 “2023-04-24 16:25:40”

dafa944c1509418e89b896f7c37eadff.png

 

再看一下 insert into 存放数据的时候的相关 包的情况

整个 sql 语句是通过字符串的形式 交互给 mysql, mysql 自行解析 处理

0fc6a991a61d47fd9d8d01f8f968b71a.png

 

 

所以 客户端这边拿到的 datetime 的字符串 取决于服务器的时区配置, 以及客户端请求的时区配置 

我们这边调整一下 客户端这边的 serverTimezone 的配置, 整个 url 更新成为

jdbc:mysql://10.60.50.16:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&autoReconnectForPools=true&useSSL=false&serverTimezone=GMT%2B2

 

查看一下 服务器响应的数据

服务器相应的依旧是字符串的 “2023-04-24 16:25:40”

所以说这个 serverTimeZone 的转换是在客户端这边 

4e5138b1ce484106b08682f75d851c7f.png

 

客户端这边具体的时间转换是在这里, 服务器响应回来的时间是 “2023-04-24 16:25:40”

按照 GMT+2 的时间转换为时间戳为 “1682346340906”

换算成 我们 GMT+8 的时间为 “2023-04-24 22:25:40”

d0589e27c7cb41a4b3463c572ee1df68.png

 

具体获取时区的地方, 是从 session 的 serverTimeZone 获取的, 也就是我们上面指定的 serverTimeZone

efa3073838554fe4bbd3c2a308d6ec9e.png 

业务这边查询, 拿到的是时间戳为 “1682346340906”

然后按照 GMT+8 转换一下 “2023-04-24 22:25:40”

2dc21b19895447429a3188256169d67a.png

 

 

 调整 mysql 的 default_time_zone

--default_time_zone='+02:00'

增加默认时区的配置, 然后 再来查看一下 情况

服务器这边 响应回来的数据, 依然是 “2023-04-24 16:25:40”

22fe62b36a42400590e9b0cb50ed2390.png

 

然后客户端这边 按照 GMT+2 转换为时间戳

所以说 这里 serverTimeZone 可能取自两个地方, 一个是服务器, 一个是客户端 

ceae95e1ab4f45828836c546b4f2e2a0.png

 

可以看到这里 拿到的 field1 结果也是 

GMT+2 的 “2023-04-24 16:25:40”

GMT+8 的 “2023-04-24 22:25:40”

5d132794f2cb4364beea0241b8dfc7af.png

 

我们来看一下这里 获取 serverTimeZone 的地方 

优先获取的是 客户端配置的 timeZone

其次获取的是服务器的 timeZone, 有两种配置方式 

80e2c12de1034155bacb7e9e2c08eac2.png

 

服务器这边的变量是用如下 sql 查询的, 并注册到 serverVariables 中 

8018e302d60e432e847fe1419bb69d84.png 

查询的 sql 如下 

SELECT  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@collation_connection AS collation_connection, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_write_timeout AS net_write_timeout, @@performance_schema AS performance_schema, @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@transaction_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout

63f12e6a02c84a9ca16ca8b9f78f974a.png

 

 

与客户端的交互, 获取给定的 datetime 的编码之后的 longlong 表示 

然后再 解码为目标格式 的字符串表示

cff79e3a68cf410d9589a4be7ef39b99.png

 

格式化的模板为 yyyy-MM-dd HH:mm:ss

a9f5d75dcaa94f20ae3e6006299e7a0a.png

 

 

mysql 服务器 datetime 的数据存储 

然后 我们来看一下 mysql 这边 datetime 字段的存储, 测试语句如下

客户端交互 字符串过去, 服务端拿到 这个字符串会做什么处理呢?

insert into tz_zone (field1) values ('2023-04-24 16:25:40');

 

首先如下地方是 将字符串转换为 MYSQL_TIME 的结构体, 处理就是解析出 年月日, 时分秒 等等信息 放到 MYSQL_TIME 中

bbb91bdd50154b2eb4f1cb6e66e35187.png

 

解析之后 MYSQL_TIME 中存储了传入 时间所表示的 年月日, 时分秒 等等信息

11ac378230ed46349e5e92235efeadde.png 

这是具体的存储方案, 将 MYSQL_TIME 编码成为一个 longlong

存储方案 在备注中 解释的很明确

/*1 bit  sign            (used when on disk)17 bits year*13+month   (year 0-9999, month 0-12)5 bits day             (0-31)5 bits hour            (0-23)6 bits minute          (0-59)6 bits second          (0-59)24 bits microseconds    (0-999999)Total: 64 bits = 8 bytesSYYYYYYY.YYYYYYYY.YYdddddh.hhhhmmmm.mmssssss.ffffffff.ffffffff.ffffffff
*/

 13662b3fbc2e47d0ac80790cf2d420eb.png

 

 

然后 响应就是一个逆向的过程

首先 还原成 MYSQL_TIME

然后 再转换成为字符串

整个过程中可以理解为 对于时间字符串的 编码, 解码

抽象这个编码解码的过程, 可以理解为 服务器这边 存放 datetime 就是存放的一个字符串, 所以说 服务器这边 datetime的存放是不涉及时区的

28308994974f4d6c89f5ba945639b1b4.png

 

 

mysql 中 date/time/year 的机制和 datetime 类似 

com.mysql.cj.result 相关实体是将协议的 字节序列 转换为 具体的基础数据类型的数据

 

date

4f82c88026324af1a2f03752b6363951.png

 

time

c72646e5cc954311a176ff6bf3bb5213.png 

 year

1cc77ae2c15e4759bc7e02ec928730ec.png

 

timestamp

1bd3f7e1d8aa467bad98f50873936c14.png

 

 

date 的格式化 

c2fc5482b45e48abad4c58c9bf7a3ca0.png

 

 

 year 的格式化

abe0a39050b04a87a6b617594625a689.png

 

 


 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/72421.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NS2安装及入门实例——(ns2.35 / Ubuntu20.04)

文章目录 一、ns2安装1、更新系统源2、准备工作3、下载安装包4、安装5、问题① 问题1② 问题2③ 问题3 6、安装成功7、环境配置 二、nam安装1、安装2、问题 三、实例 一、ns2安装 1、更新系统源 sudo apt-get update sudo apt-get upgrade2、准备工作 sudo apt-get install …

Oracle 遍历变量游标

背景 由于我们的数据库系统中的游标特别多&#xff0c;DBA让我们优化&#xff0c;减少游标的使用。 电脑系统&#xff1a;windows数据库&#xff1a;Oracle数据库图形化界面工具&#xff1a;Toad&#xff0c;DBeaver(我測試的時候用的)记录日期&#xff1a;2023-09-04 具体实…

计算机重点学科评级B-,山东省属重点高校考情分析

山东科技大学(B-) 考研难度&#xff08;☆☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1175字预计阅读&#xff1a;3分钟 2023考情概况 山东科技大学计…

Android12之解析/proc/pid进程参数(一百六十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

记一次诡异的Cannot find declaration to go to,Cannot resolve method

记一次诡异的 Cannot find declaration to go to&#xff0c; Cannot resolve method getOnExpressions in Join 对于项目中通常问题&#xff0c;清除缓存&#xff0c;重启idea&#xff0c;或者仔细检查语法通常都能解决问题&#xff0c;但是这次却失效了&#xff0c;以下是原…

Scala面向对象编程(高级部分)

1. 静态属性和静态方法 &#xff08;1&#xff09;回顾Java中的静态概念 public static 返回值类型 方法名(参数列表) {方法体} 静态属性… 说明: Java中静态方法并不是通过对象调用的&#xff0c;而是通过类对象调用的&#xff0c;所以静态操作并不是面向对象的。 &#xff0…

深入探讨Java Stream流:数据处理的新思维

文章目录 1. 流式思想1.1 输入流与输出流1.2 Stream流 2. 使用Stream流的步骤3. 获取Stream流3.1 容器3.2 数组 4. Stream流中间操作方法4.1 filter(Predicate<? super T> predicate)4.2 limit(long maxSize)4.3 skip(long n)4.4 distinct()4.5 sorted() 和 sorted(Comp…

Java使用pdfbox将pdf转图片

前言 目前比较主流的两种转pdf的方式&#xff0c;就是pdfbox和icepdf&#xff0c;两种我都尝试了下&#xff0c;icepdf解析出来有时候会出现中文显示不出来&#xff0c;网上的解决方式又特别麻烦&#xff0c;不是安装字体&#xff0c;就是重写底层类&#xff0c;所以我选择了p…

【Spring】aop的底层原理

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理 Spring 中的切面编程aop的底层原理和重点注意的地方 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以…

人体呼吸存在传感器成品,毫米波雷达探测感知技术,引领智能家居新潮流

随着科技的不断进步和人们生活质量的提高&#xff0c;智能化家居逐渐成为一种时尚和生活方式。 人体存在传感器作为智能家居中的重要组成部分&#xff0c;能够实时监测环境中人体是否存在&#xff0c;为智能家居系统提供更加精准的控制和联动。 在这个充满创新的时代&#xf…

科技资讯|苹果Vision Pro头显申请游戏手柄专利和商标

苹果集虚拟现实和增强现实于一体的头戴式设备 Vision Pro 推出一个月后&#xff0c;美国专利局公布了两项苹果公司申请的游戏手柄专利&#xff0c;其中一项的专利图如下图所示。据 PatentlyApple 报道&#xff0c;虽然专利本身并不能保证苹果公司会推出游戏手柄&#xff0c;但是…

Redis6搭建高可用的多主多从集群

Redis6搭建高可用的多主多从集群 环境准备搭建redis6集群安装redis6修改配置文件修改cluster-enabled修改cluster-config-file修改cluster-node-timeout 启动集群 环境准备 首先我们需要6台redis&#xff0c;那么为啥是6太呢&#xff1f;是因为我们要部署多master和多slaver集…

07-Spring Cloud

1、如何设计一个注册中心&#xff1f; 高可用&#xff1a;通过集群的方式 高并发&#xff1a;减少响应时间、提高吞吐量 并发用户数等&#xff0c;通过增加服务器性能、 扩展服务实例的方式 高性能&#xff1a;程序处理速度 考虑 数据存储结构、通信机制、集群同步。 集群…

C++中引用详解!

前言&#xff1a; 本文旨在讲解C中引用的相关操作&#xff0c;以及引用的一些注意事项&#xff01;搬好小板凳&#xff0c;干货来了&#xff01; 引用的概念 何谓引用呢&#xff1f;引用其实很容易理解&#xff0c;比如李华这个同学&#xff0c;他因为很调皮&#xff0c;所以…

解密Kubernetes(K8s)集群的创建过程和关键步骤

文章目录 1. 准备环境2. 安装Docker3. 安装Kubernetes在Master节点上执行以下步骤&#xff1a;安装kubeadm、kubelet和kubectl初始化Master节点 在工作节点上执行以下步骤&#xff1a;加入集群 4. 设置Kubeconfig5. 安装网络插件6. 验证集群7. 部署应用程序8. 扩展和管理集群9.…

算法专栏——双指针

1.移动零 题目链接&#xff1a;移动 0_牛客题霸_牛客网 (nowcoder.com) 算法原理&#xff1a; 像这样子的将一整块数组划分很多部分可以称为数组划分&#xff0c;常用的解法可以是双指针。 说是双指针&#xff0c;但操作的对象是数组&#xff0c;因此下标就是指针。 双指针的…

LeetCode 48题: 旋转图像

题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]…

MySql学习笔记04——DDL

DDL 建表语法 建表属于DDL语句&#xff0c;DDL语句包括create drop alter create table 表名(字段名1 数据类型,字段名2 数据类型,字段名3 数据类型,.. );表名一般建议使用t_开头&#xff0c;可读性更强。 Mysql数据类型 varchar 可变长度的字符串&#xff0c;最长为255&…

webserver 同步 I/O 模拟 Proactor 模式的工作流程

服务器基本框架、I/O 模型、事件处理模式 一、服务器编程基本框架 虽然服务器程序种类繁多&#xff0c;但其基本框架都一样&#xff0c;不同之处在于逻辑处理。 二、五种 I/O 模型 阻塞/非阻塞、同步/异步&#xff08;网络IO&#xff09;_呵呵哒(&#xffe3;▽&#xffe3;)&…

Increment Selection 插件

Increment Selection 插件实现递增 初次使用 按下快捷键 Alt Shift 鼠标左键向下拖拽 向下拖拽之后&#xff0c;在输入一个数字&#xff0c;比如我这里输入了一个数字1 然后按下快捷键 Ctrl Shift ← 进行选中数字 然后按下快捷键 Ctrl Alt i 建自动递增。 然后鼠标随…