为什么有时候binlog文件会很大于max_binlog_size以及max_binlog_cache_size
Posted alpes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么有时候binlog文件会很大于max_binlog_size以及max_binlog_cache_size相关的知识,希望对你有一定的参考价值。
问题描述
线上一个很有意思的现象,发现binlog文件大小是15G,查看了参数max_binlog_size
是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;
[email protected]:15:20>insert into testb select * from testb limit 200; -- 3.9K Jan 30 11:15 mysql-bin.003691
[email protected]:15:28>insert into testb select * from testb limit 460; -- 12K Jan 30 11:16 mysql-bin.003691
[email protected]: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 testbG *************************** 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)
[email protected]: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
以上是关于为什么有时候binlog文件会很大于max_binlog_size以及max_binlog_cache_size的主要内容,如果未能解决你的问题,请参考以下文章