什么是Binlog?浅析MySQL中的Binlog
来源:SegmentFault
时间:2023-02-24 13:41:38 475浏览 收藏
小伙伴们有没有觉得学习数据库很有意思?有意思就对了!今天就给大家带来《什么是Binlog?浅析MySQL中的Binlog》,以下内容将会涉及到MySQL、binlog,若是在学习中对其中部分知识点有疑问,或许看了本文就能帮到你!
花瓣网的搜索架构需要重构,尤其是在索引建立或者更新层面。
目前的一个架构导致的结果就是时间越久,数据本体与搜索引擎索引中的数据越不同步,相差甚大。
新的一个架构打算从 MySQL 的 Binlog 中读取数据更新、删除、新增等历史记录,并把相应信息提取出来丢到队列中慢慢去同步。
所以我就在这里小小去了解一下 Binlog。
准备工作
什么是 Binlog
MySQL Server 有四种类型的日志——Error Log、General Query Log、Binary Log 和 Slow Query Log。
第一个是错误日志,记录 mysqld 的一些错误。第二个是一般查询日志,记录 mysqld 正在做的事情,比如客户端的连接和断开、来自客户端每条 Sql Statement 记录信息;如果你想准确知道客户端到底传了什么瞎 [哔哔] 玩意儿给服务端,这个日志就非常管用了,不过它非常影响性能。第四个是慢查询日志,记录一些查询比较慢的 SQL 语句——这种日志非常常用,主要是给开发者调优用的。
剩下的第三种就是 Binlog 了,包含了一些事件,这些事件描述了数据库的改动,如建表、数据改动等,也包括一些潜在改动,比如
v1,用于 MySQL 3.2.3
v3,用于 MySQL 4.0.2 以及 4.1.0
v4,用于 MySQL 5.0 以及更高版本
实际上还有一个 v2 版本,不过只在早期 4.0.x 的 MySQL 版本中使用过,但是 v2 已经过于陈旧并且不再被 MySQL 官方支持了。
通常我们现在用的 MySQL 都是在 5.0 以上的了,所以就略过 v1 ~ v3 版本的 Binlog,如果需要了解 v1 ~ v3 版本的 Binlog 可以自行前往上述的《High-level...》文章查看。
事件头
一个事件头有 19 字节,依次排列为四字节的时间戳、一字节的当前事件类型、四字节的服务端 ID、四字节的当前事件长度描述、四字节的下个事件位置(方便跳转)以及两字节的标识。
用 ASCII Diagram 表示如下:
+---------+---------+---------+------------+-------------+-------+ |timestamp|type code|server_id|event_length|next_position|flags | |4 bytes |1 byte |4 bytes |4 bytes |4 bytes |2 bytes| +---------+---------+---------+------------+-------------+-------+
也可以字节编造一个结构体来解读这个头:
c
struct BinlogEventHeader
{
int timestamp;
char type_code;
int server_id;
int event_length;
int next_position;
char flags[2];
};
如果你要直接用这个结构体来读取数据的话,需要加点手脚。
因为默认情况下 GCC 或者 G++ 编译器会对结构体进行字节对齐,这样读进来的数据就不对了,因为 Binlog 并不是对齐的。为了统一我们需要取消这个结构体的字节对齐,一个方法是使用
#pragma pack(n),一个方法是使用__attribute__((__packed__)),还有一种情况是在编译器编译的时候强制把所有的结构体对其取消,即在编译的时候使用fpack-struct参数,如:```sh
$ g++ temp.cpp -o a -fpack-struct=1
根据上述的结构我们可以明确得到各变量在结构体里面的偏移量,所以在 MySQL 源码里面([libbinlogevents/include/binlog_event.h](https://github.com/mysql/mysql-server/blob/5.7/libbinlogevents/include/binlog_event.h#L353))有下面几个常量以快速标记偏移: ```c #define EVENT_TYPE_OFFSET 4 #define SERVER_ID_OFFSET 5 #define EVENT_LEN_OFFSET 9 #define LOG_POS_OFFSET 13 #define FLAGS_OFFSET 17
而具体有哪些事件则在 libbinlogevents/include/binlog_event.h#L245 里面被定义。如有个
FORMAT_DESCRIPTION_EVENT事件的
type_code是 15、
UPDATE_ROWS_EVENT的
type_code是 31。
还有那个
next_position,在 v4 版本中代表从 Binlog 一开始到下一个事件开始的偏移量,比如到第一个事件的
next_position就是 4,因为文件头有一个字节的长度。然后接下去对于事件 n 和事件 n + 1 来说,他们有这样的关系:
next_position(n + 1) = next_position(n) + event_length(n)
关于 flags 暂时不需要了解太多,如果真的想了解的话可以看看 MySQL 的相关官方文档。
事件体
事实上在 Binlog 事件中应该是有三个部分组成,
header、
post-header和
payload,不过通常情况下我们把
post-header和
payload都归结为事件体,实际上这个
post-header里面放的是一些定长的数据,只不过有时候我们不需要特别地关心。想要深入了解可以去查看 MySQL 的官方文档。
所以实际上一个真正的事件体由两部分组成,用 ASCII Diagram 表示就像这样:
+=====================================+ | event | fixed part (post-header) | | data +----------------------------+ | | variable part (payload) | +=====================================+
而这个
post-header对于不同类型的事件来说长度是不一样的,同种类型来说是一样的,而这个长度的预先规定将会在一个“格式描述事件”中定好。
格式描述事件
在上文我们有提到过,在 Magic Number 之后跟着的是一个格式描述事件(Format Description Event),其实这只是在 v4 版本中的称呼,在以前的版本里面叫起始事件(Start Event)。
在 v4 版本中这个事件的结构如下面的 ASCII Diagram 所示。
+=====================================+ | event | timestamp 0 : 4 | | header +----------------------------+ | | type_code 4 : 1 | = FORMAT_DESCRIPTION_EVENT = 15 | +----------------------------+ | | server_id 5 : 4 | | +----------------------------+ | | event_length 9 : 4 | >= 91 | +----------------------------+ | | next_position 13 : 4 | | +----------------------------+ | | flags 17 : 2 | +=====================================+ | event | binlog_version 19 : 2 | = 4 | data +----------------------------+ | | server_version 21 : 50 | | +----------------------------+ | | create_timestamp 71 : 4 | | +----------------------------+ | | header_length 75 : 1 | | +----------------------------+ | | post-header 76 : n | = array of n bytes, one byte per event | | lengths for all | type that the server knows about | | event types | +=====================================+
这个事件的
type_code是 15,然后
event_length是大于等于 91 的值的,这个主要取决于所有事件类型数。
因为从第 76 字节开始后面的二进制就代表一个字节类型的数组了,一个字节代表一个事件类型的
post-header长度,即每个事件类型固定数据的长度。
那么按照上述的一些线索来看,我们能非常快地写出一个简单的解读 Binlog 格式描述事件的代码。
如上文所述,如果需要正常解读 Binlog 文件的话,下面的代码编译时候需要加上
-fpack-struct=1这个参数。
cpp
#include#include struct BinlogEventHeader { int timestamp; unsigned char type_code; int server_id; int event_length; int next_position; short flags; }; int main() { FILE* fp = fopen("/usr/local/var/mysql/master-bin.000001", "rb"); int magic_number; fread(&magic_number, 4, 1, fp); printf("%d - %sn", magic_number, (char*)(&magic_number)); struct BinlogEventHeader format_description_event_header; fread(&format_description_event_header, 19, 1, fp); printf("BinlogEventHeadern{n"); printf(" timestamp: %dn", format_description_event_header.timestamp); printf(" type_code: %dn", format_description_event_header.type_code); printf(" server_id: %dn", format_description_event_header.server_id); printf(" event_length: %dn", format_description_event_header.event_length); printf(" next_position: %dn", format_description_event_header.next_position); printf(" flags[]: %dn}n", format_description_event_header.flags); short binlog_version; fread(&binlog_version, 2, 1, fp); printf("binlog_version: %dn", binlog_version); char server_version[51]; fread(server_version, 50, 1, fp); server_version[50] = '
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
371 收藏
-
244 收藏
-
288 收藏
-
480 收藏
-
430 收藏
-
120 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 忧伤的路人
- 这篇文章内容真是及时雨啊,好细啊,感谢大佬分享,码起来,关注博主了!希望博主能多写数据库相关的文章。
- 2023-03-09 15:02:51
-
- 热情的吐司
- 很有用,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢楼主分享文章内容!
- 2023-03-08 04:42:25
-
- 苹果发箍
- 这篇技术文章出现的刚刚好,很详细,很有用,码住,关注作者大大了!希望作者大大能多写数据库相关的文章。
- 2023-03-05 17:04:15
-
- 土豪的流沙
- 好细啊,码住,感谢博主的这篇技术贴,我会继续支持!
- 2023-03-05 10:50:32
-
- 勤奋的小海豚
- 太给力了,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢楼主分享技术贴!
- 2023-03-03 12:23:30
-
- 刻苦的蜜蜂
- 太细致了,已收藏,感谢楼主的这篇文章,我会继续支持!
- 2023-02-27 03:16:56