生产问题(十六)数据丢失-mysql binlog排查

news2025/1/20 12:01:49

一、引言

    最近作者遇到一个线上问题,是mysql 的数据丢失了,这里记录一下排查过程和binlog的分析。

二、问题

    问题出现的表象是应用系统大量报错,各种空指针之类的,这种一看就不可能是代码发布的问题,原因一定在框架、网络或者数据层。

    我们首先根据日志找到了报错数据,然后在查sqlserver的时候发现是有的,但是mysql里面没有数据。

    这里要提一下作者这里的数据架构背景,目前是双引擎的,sqlserver和mysql同时双写,有一个公共组件进行写入和更新,所以我们第一想法是组件有问题。

三、排查

1、公共组件

    我们首先联系了公共组件的人,询问有无相关发布,但是很明显没有,并且公共组件还找了日志截图

    可以明显看到插入语句和更新语句都是有返回影响行数的,所以公共组件应该是没什么问题

图片

    这样的话,怀疑的方向就到了数据层,是不是mysql的库坏了,虽然很少见,但是开发团队多的确什么情况都有,隔壁的数据库经常出问题

2、数据库

    在觉得数据库有问题之后,我们就找dba导出binlog查看,这里要知道一下mysql的写入顺序。作者之前写过文章,binlog是最后写入的,在undo、redo之后,所以看数据问题binlog就可以

https://blog.csdn.net/m0_69270256/article/details/128311652?spm=1001.2014.3001.5501

图片

    先看一个单子的binlog写入,由于需要隐藏信息,这里的表和字段都呗替换成虚拟的

    begin代表事务开启,

  • end_log_pos 26:这表示事件在二进制日志文件中的结束位置是26。这个数字是一个字节偏移量,指示了下一个事件在日志文件中的起始位置。

  • CRC32 0xe1:这是一个循环冗余校验(CRC32)值,用于检测日志内容在存储或传输过程中是否发生了变化。0xe1是这个特定事件内容的CRC32校验和。

  • Query:这表明记录的事件类型是一个查询。在二进制日志中,可以记录多种类型的事件,例如Query(查询)、Xid(事务ID)、Table_map(表映射)等。

  • thread_id=666:这是执行查询的线程ID。在MySQL中,每个客户端连接都由一个线程处理,这个ID可以用来追踪是哪个线程执行了这个查询。

  • exec_time=0:这表示查询的执行时间是0秒。这个值通常用于性能分析,了解查询执行的耗时。

  • error_code=0:这表示查询执行时没有发生错误。0通常表示操作成功,非零值表示发生了错误。

    重点在于Write_rows和commit,这代表数据肯定是插入了

  • Write_rows:这表明事件的类型是写入行操作。这意味着该事件包含了被插入到表中的行的信息。

  • table id 94:这标识了行被插入的表。表ID是二进制日志文件中唯一的数字标识符,用于将事件与特定的表关联起来。要知道这个ID指的是哪个表,您需要查看二进制日志中前面的Table_map事件,该事件将表ID映射到实际的表名。

  • flags: STMT_END_F:这是与事件相关联的一组标志。特别是STMT_END_F标志表明这个Write_rows事件标志着一个语句的结束。在二进制日志的上下文中,这意味着该事件是代表单个SQL语句的一系列事件中的最后一个。

BEGIN
/*!*/;
# at 572
#523 13:15:39 server id id1  end_log_pos pos1 CRC32 0x60a16a59   Rows_query
# /*Client[MSG_ID:msgid1]*/REPLACE INTO `product` (`id`,`product`) VALUES (1,'product1')
# at pos1
#523 13:15:39 server id id1  end_log_pos 22 CRC32 0xc3   Table_map: `msdb`.`product` mapped to number 94
# at 22
#523 13:15:39 server id id1  end_log_pos 23 CRC32 0xfb   Write_rows: table id 94 flags: STMT_END_F
### INSERT INTO `msdb`.`product`
### SET
###   @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='uid1' /* VARSTRING(80) meta=80 nullable=0 is_null=0 */
###   @3='' /* VARSTRING(80) meta=80 nullable=0 is_null=0 */
# at 23
#523 13:15:39 server id id1  end_log_pos 24 CRC32 0xb1   Xid = 222
COMMIT/*!*/;
# at 24
# at 25
#523 13:15:39 server id id1  end_log_pos 26 CRC32 0xe1   Query  thread_id=666  exec_time=0  error_code=0

=134/*!*/;

    如果是被回滚了,他应该是这样的,ROLLBACK标志会非常明显,所以一定不是回滚然后没有插入

BEGIN/*!*/;
# at 572
#523 13:15:39 server id id1  end_log_pos pos1 CRC32 0x60a16a59   Rows_query
# /*Client[MSG_ID:msgid1]*/REPLACE INTO `product` (`id`,`product`) VALUES (1,'product1')
# at pos1
#523 13:15:39 server id id1  end_log_pos 22 CRC32 0xc3   Table_map: `msdb`.`product` mapped to number 94
# at 22
#523 13:15:39 server id id1  end_log_pos 23 CRC32 0xfb   Write_rows: table id 94 flags: STMT_END_F
### INSERT INTO `msdb`.`product`
### SET
###   @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='product1' /* VARSTRING(80) meta=80 nullable=0 is_null=0 */
# at 23
#523 13:15:39 server id id1  end_log_pos 24 CRC32 0xb1   Xid = 222
ROLLBACK/*!*/;
# at 24

    而且后续还能看到更新这条数据的binlog,同样说明了数据是进入数据库的

BEGIN/*!*/;
# at 572
#523 13:15:39 server id id1  end_log_pos pos1 CRC32 0x60a16a59   Rows_query
# /*Client[MSG_ID:msgid1]*/UPDATE `product` SET `product`='product2' WHERE `id`=1
# at pos1
#523 13:15:39 server id id1  end_log_pos 22 CRC32 0xc3   Table_map: `msdb`.`product` mapped to number 94
# at 22
#523 13:15:39 server id id1  end_log_pos 23 CRC32 0xfb   Update_rows: table id 94 flags: STMT_END_F
### UPDATE `msdb`.`product`
### WHERE
###   @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='product1' /* VARSTRING(80) meta=80 nullable=0 is_null=0 */
### SET
###   @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='product2' /* VARSTRING(80) meta=80 nullable=0 is_null=0 */
# at 23
#523 13:15:39 server id id1  end_log_pos 24 CRC32 0xb1   Xid = 224
COMMIT/*!*/;
# at 24

   

     既然数据有了,那有没有可能是被删除了,但是我们是没有物理删除的,也没有人提工单去手工删除,

    再看看binlog找不到删除的语句,如果有应该会像下面的语句一样

    但是binlog也不是准确的,这里说的不准确不是说mysql服务器的binlog不准确,而是dba提供的下载工具。这种下载工具一般是计算好文件偏移量,然后进行多线程读取,但是文件在不断写入又被读取,事关数据库也不会锁文件,这中间有offset偏移是很正常的,所以下载的文件流很容易丢失和读取偏移。

BEGIN/*!*/;
# at 572
#523 13:15:39 server id id1  end_log_pos pos1 CRC32 0x60a16a59   Rows_query
# /*Client[MSG_ID:msgid1]*/DELETE FROM `product` WHERE `id`=1 AND `product`='product1'
# at pos1
#523 13:15:39 server id id1  end_log_pos 22 CRC32 0xc3   Table_map: `msdb`.`product` mapped to number 94
# at 22
#523 13:15:39 server id id1  end_log_pos 23 CRC32 0xfb   Delete_rows: table id 94 flags: STMT_END_F
### DELETE FROM `msdb`.`product`
### WHERE
###   @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='product1' /* VARSTRING(80) meta=80 nullable=0 is_null=0 */
# at 23
#523 13:15:39 server id id1  end_log_pos 24 CRC32 0xb1   Xid = 223
COMMIT/*!*/;
# at 24

    到这里就有点坑了,不能纠结到底是不是binlog下载丢失,也有可能是就没有删除日志。好在后面又找到了一个两天前的老单子,在mysql对应bi 的数据库里面有数据,因为bi库都是T-1的,所以可以证明数据的确是被删除了

    后面换方向排查db审批工单的确发现是被删除了,属于误操作删除

三、拓展

    有的读者可能不太了解binlog,作者这里讲讲它的原理和使用

1、原理

  1. 日志格式:MySQL支持三种binlog格式:statement-based replication (SBR),row-based replication (RBR),和mixed-mode replication。SBR记录SQL语句,RBR记录行的变化,mixed模式根据操作自动选择SBR或RBR。

  2. 日志内容:binlog记录了所有修改数据库状态的SQL语句,如INSERT、UPDATE、DELETE,以及DDL语句如CREATE TABLE、ALTER TABLE等。

  3. 日志作用:

    • 复制:在主从复制中,从服务器会读取主服务器的binlog来复制数据。

    • 数据恢复:可以使用binlog来恢复因操作错误或其他原因丢失的数据。

    • 审计:binlog可以用来审计数据库的变更历史。

  4. 日志索引:MySQL会维护一个binlog索引文件,记录所有binlog文件的列表。

2、操作

  1. 启用binlog:在my.cnf(或my.ini)配置文件中设置log_bin参数来启用binlog。

  2. 查看binlog:可以使用SHOW BINARY LOGS命令查看当前的binlog文件列表。

  3. 读取binlog:使用mysqlbinlog工具可以读取和解析binlog文件。

  4. 刷新binlog:使用FLUSH LOGS命令可以关闭当前的binlog文件并开启一个新的binlog文件。

  5. 清理binlog:可以设置expire_logs_days参数来自动删除旧的binlog文件,或者使用PURGE BINARY LOGS命令手动删除。

3、使用经验

  1. 选择合适的日志格式:根据应用场景选择SBR、RBR或mixed模式。RBR更精确但可能产生更大的日志文件,SBR更易读但在某些情况下可能导致数据不一致。

  2. 监控binlog空间:binlog可能会占用大量磁盘空间,需要定期监控和清理。

  3. binlog备份:定期备份binlog文件,以便在需要时进行数据恢复。

  4. 安全考虑:binlog中可能包含敏感信息,需要确保binlog文件的安全。

  5. 性能影响:虽然binlog对性能有一定影响,但通常这种影响是可以接受的。如果性能是关键考虑因素,可以考虑使用SSD来存储binlog文件。

  6. 使用mysqlbinlog工具:熟悉mysqlbinlog工具的使用,它可以帮助你解析、过滤和应用binlog事件。

  7. 测试恢复流程:定期测试使用binlog的数据恢复流程,确保在紧急情况下能够快速有效地恢复数据。

四、总结

    业务场景,读者们和作者可能不一样,但是这个排查思路和binlog分析都是可以学习的经验。

图片

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

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

相关文章

springboot+vue 社区养老服务系统

Springbootvue社区居家养老服务系统,数据库mysql,mybatis框架,有可视化页面。 功能: 用户管理 养老服务管理 护理人员管理 服务类型管理 健康状况管理 社区管理 服务区管理 娱乐资讯管理 咨询分类管理 反馈建议 系统简历管理 轮播…

华为telnet的两种认证方式

华为telnet的两种认证方式 实验拓扑: 实验要求: 1.采用普通密码认证实现telnet 远程登录机房设备R3 2.采用AAA认证服务方式实现telnet 远程登录机房设备R3 实验步骤: 1.完成基本配置(设备接口配置IP,此步骤略过&#…

2024上海中小学生古诗文大会方案已发布,家长孩子最关心10个问题

昨天(2024年5月30日)下午15点,上海中小学生古诗文大会组委会通过两个公众号发布了《2024上海中小学生古诗文大会系列活动方案出炉》的推文(下称《方案》)。如我之前的分析和预测,5月份会发布今年的中小学生…

【如何用爬虫玩转石墨文档?】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

机器人动力学模型与MATLAB仿真

机器人刚体动力学由以下方程控制!!! startup_rvc mdl_puma560 p560.dyn 提前计算出来这些“disturbance”,然后在控制环路中将它“抵消”(有时候也叫前馈控制) 求出所需要的力矩,其中M项代表克服…

判断自守数-第13届蓝桥杯选拔赛Python真题精选

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第75讲。 判断自守数&#…

【Qt秘籍】[006]-Qt 的 Hello World程序-编程第一步

"Hello,World!" 中文意思是“你好,世界”。 因为 The C Programming Language 中使用它做为第一个演示程序,后来很多程序员在学习编程或进行设备调试时延续了这一习惯。 下面,我们也将演示Qt中的"Hello World!" 我们先创…

分享一个 ASP.NET Web Api 上传和读取 Excel的方案

前言 许多业务场景下需要处理和分析大量的数据,而 Excel 是业务人员常用的数据表格工具,因此,将 Excel 表格中内容上传并读取到网站,是一个很常见的功能,目前有许多成熟的开源或者商业的第三方库,比如 NPO…

计算机视觉与模式识别实验1-2 图像的形态学操作

文章目录 🧡🧡实验流程🧡🧡1.图像膨胀2.图像腐蚀3.膨胀与腐蚀的综合使用4.对下面二值图像的目标提取骨架,并分析骨架结构。 🧡🧡全部代码🧡🧡 🧡&#x1f9e1…

【Nginx】Nginx 日志配置

Nginx 日志配置 Nginx 主要有两种日志类型:访问日志(access log)和错误日志(error log),可以帮助监控和调试服务的运行。 1.访问日志 访问日志主要记录客户端的请求,客户端向 Nginx 发起的每…

jsp实验18 JDBC

源代码以及执行结果截图&#xff1a; admoinStudent.jsp <% page language"java" contentType"text/html; charsetutf-8" pageEncoding"utf-8"%> <%page import"java.sql.*"%> <% page import"javax.sql.DataS…

【并发程序设计】12.内存映射

12.内存映射 使一个磁盘文件与内存中的一个缓冲区相映射&#xff0c;进程可以像访问普通内存一样对文件进行访问&#xff0c;不必再调用read,write&#xff0c;更加高效。 用到的函数 mmap函数 原型&#xff1a; #include <sys/mman.h> void* mmap(void* start, size_…

芙芙工具箱app源码 开源的工具箱

该工具箱集成多种实用工具&#xff0c;提供了便捷、高效的电脑使用体验&#xff0c;这款软件具备系统优化、文件管理、网络工具等多个模块&#xff0c;能够满足用户在日常使用中的多种需求&#xff0c; 芙芙工具箱可以帮助你轻松管理文件、优化系统性能、检测网络状态等&#…

反VC情绪:加密市场需要新的分布式代币发行方式

GME事件 GME事件反应了社交媒体在金融决策中的影响力&#xff0c;散户投资者群体通过集体行动&#xff0c;改变了很多人对股市的看法和参与方式。 GME事件中&#xff0c;meme扮演了核心角色。散户投资者使用各种meme来沟通策略、激励持股行为&#xff0c;创造了一种反对华尔街…

C语言文件操作:打开关闭,读写

程序文件 源程序文件&#xff08;后缀为.c&#xff09; 目标文件&#xff08;Windows环境后缀为.obj&#xff09; 可执行文件&#xff08;Windows环境后缀为.exe&#xff09; fputc FILE* pf fopen("test.txt","w");if (pf NULL){printf("%s\n"…

scp:Linux系统本地与远程文件传输命令

scp 是Linux系统中用于在本地主机和远程主机之间进行文件传输的命令。 详细说明&#xff1a; scp 命令用于安全地将文件从一个主机传输到另一个主机&#xff0c;所有传输数据都是加密的。语法&#xff1a; scp [参数] [源文件路径] [目标主机:目标路径] 参数说明&#xff1a…

977. 有序数组的平方 - 力扣

1. 题目 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 2. 示例 3. 分析 我们当然可以遍历数组平方元素&#xff0c;然后再使用sort排序&#xff0c;但这里时间复杂度就为 O(logN) 了。 我…

appium元素定位工具_uiautomatorviewer.bat

特点&#xff1a; uiautomatorviewer是android-sdk自带的元素定位工具uiautomatorviewer只能用于安卓系统&#xff1b;它是通过截屏分析XML布局文件方式&#xff0c;来提供控件信息的查看服务 uiautomatorviewer.bat 基本使用 路径&#xff1a;这个工具是Android SDK中自带&…

php反序列化学习(3)

1、session 当session_start()被调用或者php.ini中session.auto_start为1时&#xff0c;php内部调用会话管理器&#xff0c;访问用户session被序列化后&#xff0c;存储到指定目录&#xff08;默认为/tmp&#xff09;。 漏洞产生&#xff1a;写入格式与读取格式不一致 处理器…

蓝桥杯2024国赛--备赛刷题题单

1.游戏&#xff08;单调队列&#xff09; 注意如果结果是分数&#xff0c;直接设置变量为double&#xff0c;最好不要使用把int类型乘1.0变成分数来计算。 #include <iostream> #include <queue> using namespace std; const int N1e510; //滑动窗口大小为k,最大值…