為什么有時候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;
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM