八怪:再谈 MySQL 8 这两个精准的时间戳

news2024/12/26 23:20:55

MySQL 8.0 的 binlog 中多了 immediate_commit_timestamporiginal_commit_timestamp 的信息,网上也有很多文章进行解释,最近也刚好遇到相关问题,刚好稍微学习一下。

作者:高鹏(八怪),《MySQL 主从原理》作者,深入透彻理解 MySQL 主从,GTID 相关技术知识。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文共约 1700 字,预计阅读需要 6 分钟。

相关解释

  • immediate_commit_timestamp:代表是当前数据库提交的时间,从库/主库都分别代表其提交的时间。
  • original_commit_timestamp:代表主库提交的时间,不管有多少级联的从库这个时间永远是主库提交事务时候的时间。当然在主库上其就等于 immediate_commit_timestamp 的时间。

它们的生成时间都是在从 binlog cache 写入到 binlog 文件的时候,生成 GTID event 的时候,也就是 commit 的 flush 阶段,我们简称这个为 提交时间

但是需要注意的是 MGR 中主库的 original_commit_timestampimmediate_commit_timestamp 生成稍有提前(group_replication_trans_before_commit),并不是这里说的提交时间。

生成流程

2.1 关于 thd->variables.original_commit_timestamp

因为 original_commit_timestamp 来自这个值,一般情况下其值都是 UNDEFINED_COMMIT_TIMESTAMP,但是从库上这个值会在应用 GTID event 的时候更改为主库带过来的 original_commit_timestamp*,因为主库 *original_commit_timestamp 就是提交时间,因此从库的 thd->variables.original_commit_timestamp 也就设置为了主库的提交时间。

但是有一个例外,就是 5.7 向 8.0 同步的时候,因为没有这个值因此会被设置为 0。如下:

# original_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
# immediate_commit_timestamp=1703237689977004 (2023-12-22 17:34:49.977004 CST)

2.2 生成方式

这个其实比较简单,就是在函数 MYSQL_BIN_LOG::write_transaction 中生成的,大概为:

immediate_commit_timestamp = 获取的当前时间
original_commit_timestamp = thd->variables.original_commit_timestamp
(前面描述了thd->variables.original_commit_timestamp主库不会设置为特定的值,其为 UNDEFINED_COMMIT_TIMESTAMP)

如果 original_commit_timestamp 等于 UNDEFINED_COMMIT_TIMESTAMP,那么它就是主库,应该将设置
original_commit_timestamp = immediate_commit_timestamp,这样主库的 original_commit_timestamp 
和 immediate_commit_timestamp 就相同了

否则 original_commit_timestamp 有特定的值,那么就是从库,因为这个值来自 
thd->variables.original_commit_timestamp,前面说了他是应用 GTID event 的值。

2.3 相关警告

当发现从库的提交时间还比主库的提交时间更慢的时候,显然这是不合适的,就会出现这个警告如下:

if (original_commit_timestamp > immediate_commit_timestamp &&
        !thd->rli_slave->get_c_rli()->gtid_timestamps_warning_logged) { //如果原始时间 还在于了当前服务器的提交时间,这是常见的警告
      LogErr(WARNING_LEVEL, ER_INVALID_REPLICATION_TIMESTAMPS);         //则报警

这就是大家经常遇到的警告。

Invalid replication timestamps: original commit timestamp is more recent than the 
immediate commit timestamp. This may be an issue if delayed replication is active.
 Make sure that servers have their clocks set to the correct time. No further 
message will be emitted until after timestamps become valid again." 

其运维中的意义

3.1 在延时从库中的应用

如果配置了延迟从库,则使用的是 immediate_commit_timestamp 作为延迟从库应用 event 的计算标准,因为这里 event 来自 relay log,因此 immediate_commit_timestamp 是 IO 线程连接库(A->B->C,C 为延迟从库,则这里为B库提交事务的时间)的事务提交时间,在函数 sql_delay_event 中有如下计算方式:

sql_delay_end = ceil((static_cast<Gtid_log_event *>(ev)
                          ->immediate_commit_timestamp) /
                     1000000.00) +
                sql_delay; 

而对于不支持的延时从库则计算为:

sql_delay_end = ev->common_header->when.tv_sec +
                rli->mi->clock_diff_with_master + sql_delay;

对于 immediate_commit_timestampev->common_header->when.tv_sec 是有很大区别的,后者为 binlog header 中 timestamp 的时间,其在整个复制链路中并不会改变,其几乎为命令发起的时间,而不是事务提交的时间。我们以 A->B->C 为列,其中 C 为一个延迟从库。

  • 支持 immediate_commit_timestamp 的情况:C 的延迟计算是以B库提交时刻的时间为计算标准的。也就是其延迟是 B 库提交后多久 C 库应用。
  • 不支持 immediate_commit_timestamp 的情况:C 的延迟计算是以 A 库命令发起的时间为计算标准的。也就是其延迟是 A 库命令发起后多久 C 库应用。

很显然前者的计算方式更为靠谱。在延迟从库在等待的时候其线程的状态为:

Waiting until MASTER_DELAY seconds after master executed event

3.2 主库判定事务的提交时刻和语句发起时间

某些时候我们可能需要知道语句什么时候发起执行的,什么时候提交完成的,这个时候我们考虑使用 immediate_commit_timestamp 和 event header 的 timestamp 进行对比。

  • 对于自动提交的 DML 语句,则 GTID event header 的 timestamp 为语句发起的时间,而 GTID event 的 immediate_commit_timestamp 为事务提交的时间,如果差值太大,可能是遇到了锁(MDL LOCK 或 row lock)之类的问题。如下图:

image-1.png

image-2.png

  • 对于非自动提交的事务,则 GTID event 的 immediate_commit_timestamp 为事务提交的时间,但是语句开始执行的时间需要查看具体语句的 event 才可以,不能查看 GTID event header 的 timestamp,这是 commit 命令发起的时间,如下图:

image-3.png

image-4.png

当然类似,还可以获取从库的 binlog 信息来比对主库是什么时候发起语句的,什么时候提交事务的,从库又是什么时候提交事务的。类似如下图,这是我的一个从库,我这里是一个自动提交的 DML 语句

image-5.png

很明显,主库发起语句时间和主库提交时间以及从库提交时间都有一定的差值。

  • 主库发起语句时间:12:02:09
  • 主库提交事务时间:12:02:13
  • 从库提交事务时间:12:03:59

3.3 更加精确的延迟

这部分你在官方文档有说明,其中主要包含 3 个视图:

  • ps.replication_applier_status_by_worker: SQL 线程或者 WORKER 执行相关
  • ps.replication_connection_status: IO 线程相关
  • ps.replication_applier_status_by_coordinator: 协调线程相关

其中大部分和 timestamp 相关的字段的都是自解释的,而在 ps.replication_applier_status_by_coordinatorps.replication_applier_status_by_worker 中有两类字段类似 XXX_BUFFER_TIMESTAMPXXX_APPLY_TIMESTAMP 比如:

  • LAST_PROCESSED_TRANSACTION_END_BUFFER_TIMESTAMP: 表示协调线程将事务分发给 WORKER 线程的时间
  • LAST_APPLIED_TRANSACTION_END_APPLY_TIMESTAMP: 表示应用完事务的时间

具体代码中可以断点在:

  • Relay_log_info::finished_processing
  • Relay_log_info::started_processing

上进行观察,实际上是 Relay_log_info 中多了如下信息:

  /**
    Stores information on the last processed transaction or the transaction
    that is currently being processed.

    STS:
    - timestamps of the currently applying/last applied transaction

    MTS:
    - coordinator thread: timestamps of the currently scheduling/last scheduled
      transaction in a worker's queue
    - worker thread: timestamps of the currently applying/last applied
      transaction
  */
  Gtid_monitoring_info *gtid_monitoring_info;

每个 WORKER 和协调线程都包含了这样一个事务的监控信息,因此可以在视图中打印出来。

显然我们就可以通过各种从库中执行的 timestamp 的时间和主库提交时间也就是 ORIGINAL_COMMIT_TIMESTAMP 计算出来精确的延迟。

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。

SQLE 获取

类型地址
版本库https://github.com/actiontech/sqle
文档https://actiontech.github.io/sqle-docs/
发布信息https://github.com/actiontech/sqle/releases
数据审核插件开发文档https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse

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

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

相关文章

手把手将ReactJS项目部署到Ubuntu

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 1.构建项目 npm run build 生成build目录&#xff1a; 2.上传项目 将build目录上传到Ubuntu。 可以使用Xftp工具。 3.启动项目 npm install -g serve serve -s …

原生JS做别踩白块游戏

思路 创建初始一个按钮并为他添加点击监听开始创建随机方块&#xff0c;并样式_box.offsetTop speed px结合setInterval使得方块不断下移创建和删除方块的原则&#xff1a;box.offsetTop>0&#xff08;可视区上部没有方块了&#xff09;时候需要创建一行方块&#xff0c;…

Apache DolphinScheduler 社区 2023 年度工作报告

随着 2023 年的日历逐渐翻至最后一页&#xff0c;我们欣喜地回顾 Apache DolphinScheduler 社区在这一年中所取得的成就和进步。这一年&#xff0c;我们不仅在社区规模和技术发展上取得了显著成就&#xff0c;还发布了大量的技术文章和博客&#xff0c;进一步丰富了我们的知识库…

【Java进阶篇】Java中Timer实现定时调度的原理(解析)

Java中Timer实现定时调度的原理 ✔️ 引言✔️JDK 中Timer类的定义✔️拓展知识仓✔️优缺点 ✔️ 引言 Java中的Timer类是用于计划执行一项任务一次或重复固定延迟执行的简单工具。它使用一个名为TaskQueue的内部类来存储要执行的任务&#xff0c;这些任务被封装为TimerTask对…

条款16:成对使用 new 和 delete 时要采用相同形式

下面程序的行为是未定义的。至少&#xff0c;stringArray指向的100个string对象中有99个不太可能被正确地析构。 被delete的指针指向单个对象还是一个对象数组&#xff1f;内存数组通常包括数组的大小&#xff0c;delete可以知道需要调用多少个析构函数。 使用delete时使用了方…

SpringBoot 接口对枚举类型的入参以及出参的转换处理

目录 1、在项目中使用枚举类型2、不做任何处理的演示效果2.1、接口出参2.2、接口入参 3、用枚举的code作为参数和返回值3.1 代码案例3.1.1、定义枚举基础接口BaseEnum&#xff0c;每个枚举都实现该接口3.1.2、性别Sex枚举并实现接口BaseEnum3.1.3、定义BaseEnum枚举接口序列化3…

前端工程化回顾-vite 构建神器

1.构建vite 项目 pnpm create vite2.常用的配置&#xff1a; 1.公共资源路径配置&#xff1a; base: ./, 默认是/2.路径别名配置&#xff1a; resolve: {alias: {: path.resolve(__dirname, ./src),ass: path.resolve(__dirname, ./src/assets),comp: path.resolve(__dirnam…

正则表达式 详解,10分钟学会

大家好&#xff0c;欢迎来到停止重构的频道。 本期我们讨论正则表达式。 正则表达式是一种用于匹配和操作文本的工具&#xff0c;常用于文本查找、文本替换、校验文本格式等场景。 正则表达式不仅是写代码时才会使用&#xff0c;在平常使用的很多文本编辑软件&#xff0c;都…

多模态大模型Vary:扩充视觉Vocabulary,实现更细粒度的视觉感知

前言 现代大型视觉语言模型(LVLMs)具有相同的视觉词汇- CLIP&#xff0c;它可以涵盖大多数常见的视觉任务。然而&#xff0c;对于一些需要密集和细粒度视觉感知的特殊视觉任务&#xff0c;例如文档级OCR或图表理解&#xff0c;特别是在非英语场景下&#xff0c;clip风格的词汇…

盛最多水的容器(力扣11题)

例题&#xff1a; 分析&#xff1a; 这道题给出了一个数组&#xff0c;数组里的元素可以看成每一个挡板&#xff0c;要找到哪两个挡板之间盛的水最多&#xff0c;返回盛水量的最大值。这其实是一个双指针问题。 我们可以先固定第一个挡板( i )和最后一个挡板( j )&#xff0c…

FreeRTOS——计数型信号量知识总结及实战

1计数型信号量概念 1&#xff09;计数型信号量相当于队列长度大于1 的队列&#xff0c;因此计数型信号量能够容纳多个资源 2&#xff09;适用场景&#xff1a; 事件计数&#xff1a; 当每次事件发生后&#xff0c;在事件处理函数中释放计数型信号量&#xff08;计数值1&#x…

mysql查询表里的重复数据方法:

1 2 3 4 INSERT INTO hk_test(username, passwd) VALUES (qmf1, qmf1),(qmf2, qmf11) delete from hk_test where usernameqmf1 and passwdqmf1 MySQL里查询表里的重复数据记录&#xff1a; 先查看重复的原始数据&#xff1a; 场景一&#xff1a;列出username字段有重读的数…

【算法每日一练]-dfs bfs(保姆级教程 篇8 )#01迷宫 #血色先锋队 #求先序排列 #取数游戏 #数的划分

目录 今日知识点&#xff1a; 使用并查集映射点&#xff0c;构造迷宫的连通块 vis计时数组要同步当回合的处理 递归求先序排列 基于不相邻的取数问题&#xff1a;dfs回溯 n个相同球放入k个相同盒子&#xff1a;dfs的优化分支暴力 01迷宫 血色先锋队 求先序排列 取数游…

[Android]RadioButton控件

RadioButton控件 RadioButton控件是单选按钮控件&#xff0c;它继承自Button控件&#xff0c;可以直接使用Button控件支持的各种属性和方法。 与普通按钮不同的是&#xff0c;RadioButton控件多了一个可以选中的功能&#xff0c;能额外指定一个android&#xff1a;checked属性…

谷歌Gemini模型,碾压GPT-4!

谷歌Gemini 1.0革新&#xff0c;推出Gemini Ultra、Gemini Pro和Gemini Nano模型。Gemini Ultra强大但慢&#xff0c;Gemini Pro通用&#xff0c;Gemini Nano高效。Gemini模型在多领域与ChatGPT竞争&#xff0c;尤其Gemini Pro已应用于Bard。Gemini模型预计将在2024年通过Bard …

c语言结构体学习

文章目录 前言一、结构体的声明1&#xff0c;什么叫结构体?2&#xff0c;结构体的类型3,结构体变量的创建和初始化4&#xff0c;结构体的类型5&#xff0c;结构体的初始化 二、结构体的访问1&#xff0c;结构体成员的点操作符访问2&#xff0c;结构体体成员的指针访问 三、结构…

【解决】Unity 设置跨设备分辨率表现

开发平台&#xff1a;Unity 2018版本以上 开发语言&#xff1a;CSharp 编程平台&#xff1a;Visual Studio 2022   问题描述 使用 UnityEngine.dll 中关于设置分辨率的方法时&#xff0c;无法满足应用以设定分辨率进行屏幕显示问题。因而造成画面不同程度的拉伸情况。而这种情…

【Java】接口和抽象类有什么共同点和区别?

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 【Java】接口和抽象类有什么共同点和区别&…

工作流入门这篇就够了!

总概 定义&#xff1a;工作流是在计算机支持下业务流程的自动或半自动化&#xff0c;其通过对流程进行描述以及按一定规则执行以完成相应工作。 应用&#xff1a;随着计算机技术的发展以及工业生产、办公自动化等领域的需求不断提升&#xff0c;面向事务审批、材料提交、业务…

力扣hot100 对称二叉树 递归 队列

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f468;‍&#x1f3eb; 参考思路 递归的难点在于&#xff1a;找到可以递归的点 为什么很多人觉得递归一看就会&#xff0c;一写就废。 或者说是自己写无法写出来&#xff0c;关键就是你对递归理解的深不深。 对于此题&#xf…