爲何有時候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進行測試html

第二個問題,以上面的設置爲例,在文件快到1G的時候,若是來了一個大事務,這個大事務接近20G,那麼是否是能夠任務binlog文件的最大可能值是接近1G+20G=21G呢,由於超過max_binlog_cache_size就會報錯了。這個也是能夠測試下的。mysql

實驗證實

  問題1:實驗測試sql

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,才存在刷盤的操做。app

 

 問題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在文件大小上可能比實際設置的值要大,見下問題。全部嚴格來說應該是大於二者的和的。

 

在實驗的過程當中碰見一個新問題ui

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  this

能正常插入證實內存中產生的binlog應該是小於4096的,可是實際在binlog中看見的確實7286,明顯是比4094大的,爲啥會這樣呢,在從內存中把binlog落盤的過程當中作了什麼處理嗎?spa

 

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)code

 以上是表結構以及MySQL的版本

 

若有任何問題,歡迎指正。server

參考文獻:

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

相關文章
相關標籤/搜索