什么是 binlog( binary log)
binlog 是一个二进制格式的文件,用于记录用户对数据库更新的 SQL 语句信息,例如更改数据库表和更改内容的 SQL 语句都会记录到 binlog 里,但是对库表等内容的查询不会记录。 默认情况下,binlog 日志是二进制格式的,不能使用查看文本工具的命令(比如,cat,vi 等)查看,而使用 mysqlbinlog 解析查看。
Log_name (文件的名称) The name of the file that is being listed. Pos (事件开始位置) The position at which the event occurs. Event_type(事件类型) An identifier that describes the event type. Server_id The server ID of the server on which the event originated. End_log_pos (下个事件开始位置) The position at which the next event begins, which is equal to Pos plus the size of the event. Info(有关事件类型的详细信息) More detailed information about the event type. The format of this information depends on the event type.
为什么要有 binlog
主要作用是用于数据库的主从复制及数据的增量恢复。
主从复制
MySQL 上下分为 SQL 层和引擎层,不同存储引擎中的日志格式是不同的,由于要对多引擎支持,必须在 SQL 层设计逻辑日志以透明化不同存储引擎,而这个逻辑日志就是 binlog 。
当有数据修改请求时,primary 会产生包含该修改操作的 binlog,并发送给 replica,replica 通过回放该 binlog 以执行和 primary 同样的修改。此外还可用于备份点还原。
单纯的 binlog 只能用于归档,不具备 crash-safe 的能力 InnoDB 引擎为了解决 crash-safe,利用 binlog+redo log 实现了 crash-safe 能力
Master:
binlog dump thread 当数据变更时,通知所有的 slave
Slave:
I/O :接收到 binlog events 后 写入本地 relay log
SQL Thread: 读取 relay-log ,根据读取的内容转换为 sql 并重放
增量恢复
恢复方式:mysql 将保存在 binlog 日志中指定段落区间的 sql 语句逐个重新执行一次。
WAL 技术:Write-Ahead Logging 中文解释为预写日志技术。在 mysql 体现在写操作时不是立刻更新到磁盘,
而是先落在日志系统.
对支持事务的引擎如 InnoDB 而言,必须要提交了事务才会记录 binlog 。binlog 什么时候刷新到磁盘跟参数 sync_binlog 相关。
如果 sync_binlog=0 或 sync_binlog 大于 1,当发生电源故障或操作系统崩溃时,可能有一部分已提交但其 binlog 未被同步到磁盘的事务会被丢失,恢复程序将无法恢复这部分事务.
通过使用 mysqlbinlog 工具来恢复数据
事务 binlog event 写入流程
binlog cache :它是用于缓存 binlog event 的内存,大小由 binlog_cache_size 控制
binlog cache 临时文件:是一个临时磁盘文件,存储由于 binlog cache 不足溢出的 binlog event,该文件名字由 ”ML” 打头,由参数 max_binlog_cache_size 控制该文件大小
binlog file :代表 binglog 文件,由 max_binlog_size 指定大小
binlog event :代表 binlog 中的记录,如 MAP_EVENT/QUERY EVENT/XID EVENT/WRITE EVENT 等
binlog 的写入机制:事务执行的过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中。大致流程如下:
1、事务开启 2、执行 dml 语句,在 dml 语句第一次执行的时候会分配内存空间 binlog cache 3、执行 dml 语句期间生成的 event 不断写入到 binlog cache 4、如果 binlog cache 的空间已经满了,则将 binlog cache 的数据写入到 binlog 临时文件,同时清空 binlog cache。如果 binlog 临时 件的大小大于了 max_binlog_cache_size 的设置则抛错 ERROR 1197 事务提交,整个 binlog cache 和 binlog 临时文件数据全部写入到 binlog file 中,同时释放 binlog cache 和 binlog 临时文件。但是此时 binlog cache 的内存空间会被保留以供 THD 上的下一个事务使用,但是 binlog 临时文件被截断为 0,保留文件描述符。并且保留 IO_CACHE 中的分配的内存空间,和物理文件描述符 5、客户端断开连接,这个过程会释放 IO_CACHE 同时释放其持有的 binlog cache 内存空间以及持有的binlog 临时文件。
binlog 写入 cache 和临时文件
bool IO_CACHE_binlog_cache_storage::write(const unsigned char *buffer,
my_off_t length) {
return my_b_safe_write(&m_io_cache, buffer, length);
}
int my_b_safe_write(IO_CACHE *info, const uchar *Buffer, size_t Count) {
if (info->type == SEQ_READ_APPEND) return my_b_append(info, Buffer, Count);
return my_b_write(info, Buffer, Count);
}
// 如果 binlog cache 缓存当前写入的位置加上本次写入的总量大于了 binlog cache的内存地址的边界
// 则我们需要进行通过*(info)->write_function将 binlog cache 的内容写到磁盘了
// 这样才能腾出空间给新的 binlog event 存放。这个回调函数就是_my_b_write。
#define my_b_write(info, Buffer, Count)
((info)->write_pos + (Count) <= (info)->write_end
? (memcpy((info)->write_pos, (Buffer), (size_t)(Count)),
((info)->write_pos += (Count)), 0)
: (*(info)->write_function)((info), (uchar *)(Buffer), (Count)))
int _my_b_write(IO_CACHE *info, const uchar *Buffer, size_t Count) {
size_t rest_length, length;
my_off_t pos_in_file = info->pos_in_file;
// 如果超过临时文件大小设置,则报错
if (pos_in_file + info->buffer_length > info->end_of_file) {
errno = EFBIG;
set_my_errno(EFBIG);
return info->error = -1;
}
// 首先将 binlog 内容拷贝至内存 cache,将 cache 填满
rest_length = (size_t)(info->write_end - info->write_pos);
memcpy(info->write_pos, Buffer, (size_t)rest_length);
Buffer += rest_length;
Count -= rest_length;
info->write_pos += rest_length;
if (my_b_flush_io_cache(info, 1)) return 1;
if (Count >= IO_SIZE) { /* Fill first intern buffer */
length = Count & (size_t) ~(IO_SIZE - 1);
...
if (mysql_file_write(info->file, Buffer, length, info->myflags | MY_NABP))
return info->error = -1;
...
Count -= length;
Buffer += length;
info->pos_in_file += length;
}
memcpy(info->write_pos, Buffer, (size_t)Count);
info->write_pos += Count;
return 0;
}
总结
通过本篇 binlog 入门了解什么是 binlog 以及 binlog 的基础的使用场景、理解 binlog 日志是如何产生的。
参考资料
mysql.taobao.org/monthly/202…
blog.csdn.net/f80407515/a…
推荐阅读
ASM 字节码增强
浅谈表单受控性及结合Hooks应用
Mybatis一级缓存问题
MySQL死锁浅析
探索Taro:跨平台开发的实践与原理
招贤纳士
政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。
如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com
微信公众号
文章同步发布,政采云技术团队公众号,欢迎关注