欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

为什么有时候binlog文件会很大于max_binlog_size以及max_binlog_cache_size

程序员文章站 2022-04-13 15:56:08
问题描述 线上一个很有意思的现象,发现binlog文件大小是15G,查看了参数max_binlog_size是1073741824[1G], max_binlog_cache_size是21474836480[20G]。那么为什么会文件大小会超过max_binlog_file_size的设置。这个问 ......

问题描述

线上一个很有意思的现象,发现binlog文件大小是15g,查看了参数是1073741824[1g], max_binlog_cache_size是21474836480[20g]。那么为什么会文件大小会超过max_binlog_file_size的设置。这个问题比较好理解,如果是大事务呢?那么这里有一个小问题,binlog里面是以event为单位来记录的,那么事务有可能跨binlog吗?使用begin;***;***;commit进行测试

第二个问题,以上面的设置为例,在文件快到1g的时候,如果来了一个大事务,这个大事务接近20g,那么是不是可以任务binlog文件的最大可能值是接近1g+20g=21g呢,因为超过max_binlog_cache_size就会报错了。这个也是可以测试下的。

实验证明

  问题1:实验测试

root@test10:39:24>set global max_binlog_size=4096;

root@test10:48:23>begin;
query ok, 0 rows affected (0.00 sec)

root@test10:48:39>insert into testb select * from testa limit 32;
query ok, 32 rows affected (0.00 sec)
records: 32  duplicates: 0  warnings: 0

root@test10:49:05>insert into testb select * from testa limit 32;
query ok, 32 rows affected (0.00 sec)
records: 32  duplicates: 0  warnings: 0

root@test10:49:10>insert into testb select * from testa limit 32;
query ok, 32 rows affected (0.00 sec)
records: 32  duplicates: 0  warnings: 0

root@test10:49:14>insert into testb select * from testa limit 32;
query ok, 32 rows affected (0.00 sec)
records: 32  duplicates: 0  warnings: 0

root@test10:49:18>commit;
query ok, 0 rows affected (0.00 sec)

# at 3994  -- 上一个event结束的地方
#190130 10:49:14 server id 21036055 end_log_pos 4064 crc32 0x64e8a1c6 rows_query
# insert into testb select * from testa limit 32
# at 4064
#190130 10:49:14 server id 21036055 end_log_pos 4113 crc32 0x7ef21b8c table_map: `test`.`testb` mapped to number 11496
# at 4113
#190130 10:49:14 server id 21036055 end_log_pos 4692 crc32 0xfc3f78bd write_rows: table id 11496 flags: stmt_end_f  -- 这已经是下一个insert 语句了,在一个binlog文件中,说明binlog是以事务为单位来进行切割的,不是事务里面的单个sql语句,这也是比较好理解的,因为事务只有执行完了, 才能在内存中生成完整的binlog,才存在刷盘的操作。

 

 问题2:实验测试

root@test11:01:52>set global  max_binlog_cache_size=4096;
root@test11:15:20>insert into testb select * from testb limit 200; -- 3.9k jan 30 11:15 mysql-bin.003691
root@test11:15:28>insert into testb select * from testb limit 460; -- 12k jan 30 11:16 mysql-bin.003691
root@test11:17:34>insert into testb select * from testb limit 470; -- 最大就是在460到470之间
error 1197 (hy000): multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
这个实验说明binlog文件最大应该是max_binlog_size + max_binlog_cache_size的和,但是max_binlog_cache_size在文件大小上可能比实际设置的值要大,见下问题。所有严格来讲应该是大于两者的和的。

 

在实验的过程中遇见一个新问题

root@test11:07:21>insert into testb select * from testb limit 400;

# at 331
#190130 11:07:32 server id 21036055 end_log_pos 402 crc32 0x62bb0a5e rows_query
# insert into testb select * from testb limit 400
# at 402
#190130 11:07:32 server id 21036055 end_log_pos 451 crc32 0x3177b22e table_map: `test`.`testb` mapped to number 11496
# at 451
#190130 11:07:32 server id 21036055 end_log_pos 7286 crc32 0x35efff16 write_rows: table id 11496 flags: stmt_end_f  

能正常插入证明内存中产生的binlog应该是小于4096的,但是实际在binlog中看见的确实7286,明显是比4094大的,为啥会这样呢,在从内存中把binlog落盘的过程中做了什么处理吗?

 

root@test11:21:01>show create table testb\g
*************************** 1. row ***************************
       table: testb
create table: create table `testb` (
  `a` bigint(20) default null,
  `b` bigint(20) default null
) engine=innodb default charset=utf8mb4 collate=utf8mb4_unicode_ci
1 row in set (0.00 sec)

root@test11:24:10>select version();
+---------------+
| version() |
+---------------+
| 5.7.21-21-log |
+---------------+
1 row in set (0.00 sec)

 以上是表结构以及mysql的版本

 

如有任何问题,欢迎指正。

参考文献:

https://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#sysvar_max_binlog_size