Skip to content

Commit

Permalink
MDEV-31404 Implement binlog_space_limit
Browse files Browse the repository at this point in the history
binlog_space_limit is a variable in Percona server used to limit the total
size of all binary logs.

This implementation is based on code from Percona server 5.7.

In MariaDB we decided to call the variable max-binlog-total-size to be
similar to max-binlog-size. This makes it easier to find in the output
from 'mariadbd --help --verbose'). MariaDB will also support
binlog_space_limit for compatibility with Percona.

Some internal notes to explain implementation notes:

- When running MariaDB does not delete binary logs that are either
  used by slaves or have active xid that are not yet committed.

Some implementation notes:

- max-binlog-total-size is by default 0 (no limit).
- max-binlog-total-size can be changed without server restart.
- Binlog file sizes are checked on startup, or if
  max-binlog-total-size is set to a value > 0, not for every log write.
  The total size of all binary logs is cached and dynamically updated
  when updating the binary log on binary log rotation.
- max-binlog-total-size is checked against existing log files during
  serverstart, binlog rotation, FLUSH LOGS, when writing to binary log
  or when max-binlog-total-size changes value.
- Option --slave-connections-needed-for-purge with 1 as default added.
  This allows one to ensure that we do not delete binary logs if there
  is less than 'slave-connections-needed-for-purge' connected.
  Without this option max-binlog-total-size would potentially delete
  binlogs needed by slaves on server startup or when a slave disconnects
  as there are then no connected slaves to protect active binlogs.
- PURGE BINARY LOGS TO ... will be executed as if
  slave-connectitons-needed-for-purge would be zero. In other words
  it will do the purge even if there is no slaves connected. If there
  are connected slaves working on the logs, these will be protected.
- If binary log is on and max-binlog-total_size <> 0 then the status
  variable 'Binlog_disk_use' shows the current size of all old binary
  logs + the state of the current one.
- Removed test of strcmp(log_file_name, log_info.log_file_name) in
  purge_logs_before_date() as this is tested in can_purge_logs()
- To avoid expensive calls of log_in_use() we cache the result for the
  last log that is in use by a slave. Future calls to can_purge_logs()
  for this binary log will be quickly detected and false will be returned
  until a slave starts working on a new log.
- Note that after a binary log rotation caused by max_binlog_size,
  the last log will not be purged directly as it is still in use
  internally. The next binary log write will purge binlogs if needed.

Reviewer:Kristian Nielsen <knielsen@knielsen-hq.org>
  • Loading branch information
montywi authored and vuvova committed Feb 14, 2024
1 parent 9933a8c commit 18dfcfd
Show file tree
Hide file tree
Showing 23 changed files with 906 additions and 46 deletions.
15 changes: 15 additions & 0 deletions mysql-test/main/mysqld--help.result
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ The following specify which files/extra groups are read (specified before remain
MINIMAL means that only metadata actually required by
slave is logged; NO_LOG NO metadata will be
logged.Default: NO_LOG.
--binlog-space-limit=#
Alias for max_binlog_total_size. Compatibility with
Percona server.
--binlog-stmt-cache-size=#
The size of the statement cache for updates to
non-transactional engines for the binary log. If you
Expand Down Expand Up @@ -619,6 +622,11 @@ The following specify which files/extra groups are read (specified before remain
exceeds this value.
--max-binlog-stmt-cache-size=#
Sets the total size of the statement cache
--max-binlog-total-size=#
Maximum space to use for all binary logs. Extra logs are
deleted on server start, log rotation, FLUSH LOGS or when
writing to binlog. Default is 0, which means no size
restrictions. See also slave_connections_needed_for_purge
--max-connect-errors=#
If there is more than this number of interrupted
connections from a host this host will be blocked from
Expand Down Expand Up @@ -1294,6 +1302,10 @@ The following specify which files/extra groups are read (specified before remain
--skip-slave-start If set, slave is not autostarted.
--slave-compressed-protocol
Use compression on master/slave protocol
--slave-connections-needed-for-purge=#
Minimum number of connected slaves required for automatic
binary log purge with max_binlog_total_size,
binlog_expire_logs_seconds or binlog_expire_logs_days.
--slave-ddl-exec-mode=name
How replication events should be executed. Legal values
are STRICT and IDEMPOTENT (default). In IDEMPOTENT mode,
Expand Down Expand Up @@ -1616,6 +1628,7 @@ binlog-optimize-thread-scheduling TRUE
binlog-row-event-max-size 8192
binlog-row-image FULL
binlog-row-metadata NO_LOG
binlog-space-limit 0
binlog-stmt-cache-size 32768
block-encryption-mode aes-128-ecb
bulk-insert-buffer-size 8388608
Expand Down Expand Up @@ -1743,6 +1756,7 @@ max-allowed-packet 16777216
max-binlog-cache-size 18446744073709547520
max-binlog-size 1073741824
max-binlog-stmt-cache-size 18446744073709547520
max-binlog-total-size 0
max-connect-errors 100
max-delayed-threads 20
max-digest-length 1024
Expand Down Expand Up @@ -1930,6 +1944,7 @@ skip-networking FALSE
skip-show-database FALSE
skip-slave-start FALSE
slave-compressed-protocol FALSE
slave-connections-needed-for-purge 1
slave-ddl-exec-mode IDEMPOTENT
slave-domain-parallel-threads 0
slave-exec-mode STRICT
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/suite/binlog/include/binlog_expire_warnings.inc
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ if ($expect_binlog_off_days_and_seconds_warning) {
}

--let $assert_file = $ofile
--let $assert_select = You need to use --log-bin to make --expire-logs-days or --binlog-expire-logs-seconds work.
--let $assert_select = You need to use --log-bin to make --expire-logs-days, --binlog-expire-logs-seconds or --max-binlog-total-size work.
--let $assert_only_after = Shutdown complete
--source include/assert_grep.inc

Expand Down
4 changes: 4 additions & 0 deletions mysql-test/suite/binlog/my.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
!include include/default_my.cnf

[mariadbd]
slave_connections_needed_for_purge=0
123 changes: 123 additions & 0 deletions mysql-test/suite/binlog/r/max_binlog_total_size.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
select @@global.max_binlog_total_size;
@@global.max_binlog_total_size
1500
select @@global.max_binlog_size;
@@global.max_binlog_size
4096
#
# MDEV-31404 Implement binlog_space_limit
#
FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
show binary logs;
Log_name File_size
binary.000001 #
binary.000002 #
binary.000003 #
binary.000004 #
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 1552
set @@global.slave_connections_needed_for_purge= 0;
# binary.000001 should be deleted now
show binary logs;
Log_name File_size
binary.000002 #
binary.000003 #
binary.000004 #
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 1183
CREATE TABLE `t1` (
`v1` int(11) DEFAULT NULL,
`v2` varchar(8000) DEFAULT NULL,
KEY `v1` (`v1`)
) engine=myisam;
INSERT INTO t1 VALUES (0,repeat("a",3000));
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 3863
# First binary should be binary.000004
show binary logs;
Log_name File_size
binary.000004 #
INSERT INTO t1 VALUES (2,repeat("b",10));
# First binary should be binary.000004
show binary logs;
Log_name File_size
binary.000004 #
binary.000005 #
FLUSH LOGS;
# First binary should be binary.000005
show binary logs;
Log_name File_size
binary.000005 #
binary.000006 #
FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
show binary logs;
Log_name File_size
binary.000008 #
binary.000009 #
binary.000010 #
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 1225
PURGE BINARY LOGS TO 'binary.000009';
# First binary should be binary.000009
show binary logs;
Log_name File_size
binary.000009 #
binary.000010 #
INSERT INTO t1 VALUES (3,repeat("c",4000));
# First binary should be binary.000010
show binary logs;
Log_name File_size
binary.000010 #
binary.000011 #
INSERT INTO t1 VALUES (4,repeat("d",3000));
# First binary should be binary.000011
show binary logs;
Log_name File_size
binary.000011 #
RESET MASTER;
show binary logs;
Log_name File_size
binary.000001 #
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 325
INSERT INTO t1 VALUES (5,"e");
FLUSH LOGS;
INSERT INTO t1 VALUES (6,repeat("f",3000));
show binary logs;
Log_name File_size
binary.000002 #
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 3647
INSERT INTO t1 VALUES (7,repeat("g",3000));
# binary.000001 should be deleted now
show binary logs;
Log_name File_size
binary.000002 #
binary.000003 #
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 7338
FLUSH LOGS;
FLUSH LOGS;
# binary.000002 should be deleted now
show binary logs;
Log_name File_size
binary.000003 423
binary.000004 423
binary.000005 379
show status like "binlog_disk_use";
Variable_name Value
Binlog_disk_use 1225
DROP TABLE IF EXISTS t1;
set @@global.slave_connections_needed_for_purge= default;
5 changes: 5 additions & 0 deletions mysql-test/suite/binlog/t/max_binlog_total_size-master.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--log-bin=binary
--max-binlog-total-size=1500
--max-binlog-size=4096
--binlog-format=row
--slave_connections_needed_for_purge=1
94 changes: 94 additions & 0 deletions mysql-test/suite/binlog/t/max_binlog_total_size.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
--source include/have_log_bin.inc
select @@global.max_binlog_total_size;
select @@global.max_binlog_size;

# Note that this test is only using MyISAM tables.
# The reason for this is that we do not want to have engine
# checkpoints in the binary log as it would change the number of
# bytes in the log, which could cause random rotations.

--echo #
--echo # MDEV-31404 Implement binlog_space_limit
--echo #

FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
source include/show_binary_logs.inc;
show status like "binlog_disk_use";
set @@global.slave_connections_needed_for_purge= 0;
--echo # binary.000001 should be deleted now
source include/show_binary_logs.inc;
show status like "binlog_disk_use";

CREATE TABLE `t1` (
`v1` int(11) DEFAULT NULL,
`v2` varchar(8000) DEFAULT NULL,
KEY `v1` (`v1`)
) engine=myisam;
INSERT INTO t1 VALUES (0,repeat("a",3000));
show status like "binlog_disk_use";
--echo # First binary should be binary.000004
source include/show_binary_logs.inc;

INSERT INTO t1 VALUES (2,repeat("b",10));
--echo # First binary should be binary.000004
# The reson why we have logs 00004 and 00005 at this point is that we first
# do a rotate and then try to purge. However as there are still existing
# xid's pointing to the 00004, we cannot yet purge 000004.
# After rotate a checkpoint record will be written to 00005 which
# will release pointers to 00004. On next binary log write or flush
# the purge will be retried and succeed.

source include/show_binary_logs.inc;

FLUSH LOGS;
--echo # First binary should be binary.000005
source include/show_binary_logs.inc;

FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
source include/show_binary_logs.inc;
show status like "binlog_disk_use";

PURGE BINARY LOGS TO 'binary.000009';
--echo # First binary should be binary.000009
source include/show_binary_logs.inc;

INSERT INTO t1 VALUES (3,repeat("c",4000));
--echo # First binary should be binary.000010
source include/show_binary_logs.inc;

INSERT INTO t1 VALUES (4,repeat("d",3000));
--echo # First binary should be binary.000011
source include/show_binary_logs.inc;

RESET MASTER;
source include/show_binary_logs.inc;
show status like "binlog_disk_use";

INSERT INTO t1 VALUES (5,"e");
FLUSH LOGS;
INSERT INTO t1 VALUES (6,repeat("f",3000));
source include/show_binary_logs.inc;
show status like "binlog_disk_use";

INSERT INTO t1 VALUES (7,repeat("g",3000));
--echo # binary.000001 should be deleted now
source include/show_binary_logs.inc;
show status like "binlog_disk_use";

FLUSH LOGS;
FLUSH LOGS;
--echo # binary.000002 should be deleted now
show binary logs;
show status like "binlog_disk_use";

--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings

set @@global.slave_connections_needed_for_purge= default;
# End of 11.4 tests
1 change: 1 addition & 0 deletions mysql-test/suite/binlog_encryption/binlog_index-master.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--slave_connections_needed_for_purge=0
1 change: 1 addition & 0 deletions mysql-test/suite/perfschema/t/show_sanity.test
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ insert into test.sanity values
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_BINLOG_CACHE_SIZE"),
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_BINLOG_SIZE"),
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_BINLOG_STMT_CACHE_SIZE"),
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_BINLOG_TOTAL_SIZE"),
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_CONNECTIONS"),
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_CONNECT_ERRORS"),
("JUNK: GLOBAL-ONLY", "I_S.SESSION_VARIABLES", "MAX_DIGEST_LENGTH"),
Expand Down
2 changes: 2 additions & 0 deletions mysql-test/suite/rpl/my.cnf
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
# E.g. after !include ../my.cnf, in your `test.cnf`, specify your configuration
# in option group e.g [mysqld.x], so that number `x` corresponds to the number
# in the rpl server topology.
[mariadbd]
slave_connections_needed_for_purge=0
49 changes: 49 additions & 0 deletions mysql-test/suite/rpl/r/max_binlog_total_size.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
include/master-slave.inc
[connection master]
#
# MDEV-31404 Implement binlog_space_limit
#
# Test that master is not deleting binary logs before slave has a
# chance to digest them
select @@global.max_binlog_total_size;
@@global.max_binlog_total_size
1500
select @@global.max_binlog_size;
@@global.max_binlog_size
4096
connection slave;
STOP SLAVE IO_THREAD;
include/wait_for_slave_io_to_stop.inc
connection master;
kill DUMP_THREAD;
CREATE TABLE `t1` (
`v1` int(11) DEFAULT NULL,
`v2` varchar(8000) DEFAULT NULL,
KEY `v1` (`v1`)
);
FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
show binary logs;
Log_name File_size
binary.000001 #
binary.000002 #
binary.000003 #
binary.000004 #
INSERT INTO t1 VALUES (0,repeat("a",3000));
show binary logs;
Log_name File_size
binary.000001 #
binary.000002 #
binary.000003 #
binary.000004 #
connection slave;
START SLAVE IO_THREAD;
connection master;
connection slave;
connection master;
DROP TABLE t1;
show binary logs;
Log_name File_size
binary.000004 #
include/rpl_end.inc
5 changes: 5 additions & 0 deletions mysql-test/suite/rpl/t/max_binlog_total_size-master.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--log-bin=binary
--max-binlog-total-size=1500
--max-binlog-size=4096
--binlog-format=row
--slave_connections_needed_for_purge=1

0 comments on commit 18dfcfd

Please sign in to comment.