mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
MDEV-31404 Implement binlog_space_limit
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>
This commit is contained in:
parent
9933a8cc88
commit
18dfcfdecf
23 changed files with 906 additions and 46 deletions
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
4
mysql-test/suite/binlog/my.cnf
Normal file
4
mysql-test/suite/binlog/my.cnf
Normal file
|
@ -0,0 +1,4 @@
|
|||
!include include/default_my.cnf
|
||||
|
||||
[mariadbd]
|
||||
slave_connections_needed_for_purge=0
|
123
mysql-test/suite/binlog/r/max_binlog_total_size.result
Normal file
123
mysql-test/suite/binlog/r/max_binlog_total_size.result
Normal file
|
@ -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;
|
|
@ -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
mysql-test/suite/binlog/t/max_binlog_total_size.test
Normal file
94
mysql-test/suite/binlog/t/max_binlog_total_size.test
Normal file
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
--slave_connections_needed_for_purge=0
|
|
@ -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"),
|
||||
|
|
|
@ -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
mysql-test/suite/rpl/r/max_binlog_total_size.result
Normal file
49
mysql-test/suite/rpl/r/max_binlog_total_size.result
Normal file
|
@ -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
mysql-test/suite/rpl/t/max_binlog_total_size-master.opt
Normal file
5
mysql-test/suite/rpl/t/max_binlog_total_size-master.opt
Normal file
|
@ -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
|
58
mysql-test/suite/rpl/t/max_binlog_total_size.test
Normal file
58
mysql-test/suite/rpl/t/max_binlog_total_size.test
Normal file
|
@ -0,0 +1,58 @@
|
|||
--source include/have_log_bin.inc
|
||||
--source include/master-slave.inc
|
||||
--source include/have_binlog_format_row.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-31404 Implement binlog_space_limit
|
||||
--echo #
|
||||
|
||||
--echo # Test that master is not deleting binary logs before slave has a
|
||||
--echo # chance to digest them
|
||||
|
||||
select @@global.max_binlog_total_size;
|
||||
select @@global.max_binlog_size;
|
||||
|
||||
--connection slave
|
||||
STOP SLAVE IO_THREAD;
|
||||
--source include/wait_for_slave_io_to_stop.inc
|
||||
--connection master
|
||||
|
||||
# Kill the dump thread
|
||||
let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`;
|
||||
|
||||
if ($id)
|
||||
{
|
||||
replace_result $id DUMP_THREAD;
|
||||
eval kill $id;
|
||||
let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Killed';
|
||||
source include/wait_condition.inc;
|
||||
}
|
||||
|
||||
CREATE TABLE `t1` (
|
||||
`v1` int(11) DEFAULT NULL,
|
||||
`v2` varchar(8000) DEFAULT NULL,
|
||||
KEY `v1` (`v1`)
|
||||
);
|
||||
|
||||
FLUSH LOGS;
|
||||
FLUSH LOGS;
|
||||
FLUSH LOGS;
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
INSERT INTO t1 VALUES (0,repeat("a",3000));
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
--connection slave
|
||||
START SLAVE IO_THREAD;
|
||||
--connection master
|
||||
|
||||
--sync_slave_with_master
|
||||
--connection master
|
||||
|
||||
# Slave is now connected. Next query should remove old binary logs.
|
||||
|
||||
DROP TABLE t1;
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
# End of 11.4 tests
|
||||
--source include/rpl_end.inc
|
|
@ -0,0 +1,41 @@
|
|||
select @@global.max_binlog_total_size;
|
||||
@@global.max_binlog_total_size
|
||||
0
|
||||
select @@session.max_binlog_total_size;
|
||||
ERROR HY000: Variable 'max_binlog_total_size' is a GLOBAL variable
|
||||
show global variables like 'max_binlog_total_size';
|
||||
Variable_name Value
|
||||
max_binlog_total_size 0
|
||||
show session variables like 'max_binlog_total_size';
|
||||
Variable_name Value
|
||||
max_binlog_total_size 0
|
||||
select * from information_schema.global_variables where variable_name='max_binlog_total_size';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
MAX_BINLOG_TOTAL_SIZE 0
|
||||
select * from information_schema.session_variables where variable_name='max_binlog_total_size';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
MAX_BINLOG_TOTAL_SIZE 0
|
||||
set global max_binlog_total_size=1;
|
||||
select @@global.max_binlog_total_size, @@global.binlog_space_limit;
|
||||
@@global.max_binlog_total_size @@global.binlog_space_limit
|
||||
1 1
|
||||
set global max_binlog_total_size=1;
|
||||
select @@global.max_binlog_total_size;
|
||||
@@global.max_binlog_total_size
|
||||
1
|
||||
set global binlog_space_limit=2;
|
||||
select @@global.max_binlog_total_size, @@global.binlog_space_limit;
|
||||
@@global.max_binlog_total_size @@global.binlog_space_limit
|
||||
2 2
|
||||
set session max_binlog_total_size=1;
|
||||
ERROR HY000: Variable 'max_binlog_total_size' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
set global max_binlog_total_size=default;
|
||||
CREATE USER user1@localhost;
|
||||
connect con2,localhost,user1,,;
|
||||
set global max_binlog_total_size=1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the BINLOG ADMIN privilege(s) for this operation
|
||||
set global binlog_space_limit=1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the BINLOG ADMIN privilege(s) for this operation
|
||||
disconnect con2;
|
||||
connection default;
|
||||
DROP USER user1@localhost;
|
|
@ -492,6 +492,16 @@ NUMERIC_BLOCK_SIZE NULL
|
|||
ENUM_VALUE_LIST NO_LOG,MINIMAL,FULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME BINLOG_SPACE_LIMIT
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT Alias for max_binlog_total_size. Compatibility with Percona server.
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 18446744073709551615
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME BINLOG_STMT_CACHE_SIZE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
|
@ -1902,6 +1912,16 @@ NUMERIC_BLOCK_SIZE 4096
|
|||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME MAX_BINLOG_TOTAL_SIZE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT 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
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 18446744073709551615
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME MAX_CONNECTIONS
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
|
@ -3392,6 +3412,16 @@ NUMERIC_BLOCK_SIZE NULL
|
|||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME SLAVE_CONNECTIONS_NEEDED_FOR_PURGE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT 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.
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
|
|
|
@ -542,6 +542,16 @@ NUMERIC_BLOCK_SIZE NULL
|
|||
ENUM_VALUE_LIST NO_LOG,MINIMAL,FULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME BINLOG_SPACE_LIMIT
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT Alias for max_binlog_total_size. Compatibility with Percona server.
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 18446744073709551615
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME BINLOG_STMT_CACHE_SIZE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
|
@ -2102,6 +2112,16 @@ NUMERIC_BLOCK_SIZE 4096
|
|||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME MAX_BINLOG_TOTAL_SIZE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT 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
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 18446744073709551615
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME MAX_CONNECTIONS
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
|
@ -3962,6 +3982,16 @@ NUMERIC_BLOCK_SIZE NULL
|
|||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME SLAVE_CONNECTIONS_NEEDED_FOR_PURGE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT 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.
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 4294967295
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME SLAVE_DDL_EXEC_MODE
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE ENUM
|
||||
|
|
42
mysql-test/suite/sys_vars/t/max_binlog_total_size_basic.test
Normal file
42
mysql-test/suite/sys_vars/t/max_binlog_total_size_basic.test
Normal file
|
@ -0,0 +1,42 @@
|
|||
# We cannot use embedded server here as access right checking will not work
|
||||
--source include/not_embedded.inc
|
||||
#
|
||||
# only global
|
||||
#
|
||||
select @@global.max_binlog_total_size;
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
select @@session.max_binlog_total_size;
|
||||
show global variables like 'max_binlog_total_size';
|
||||
show session variables like 'max_binlog_total_size';
|
||||
--disable_warnings
|
||||
select * from information_schema.global_variables where variable_name='max_binlog_total_size';
|
||||
select * from information_schema.session_variables where variable_name='max_binlog_total_size';
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# show that it is not read-only
|
||||
#
|
||||
set global max_binlog_total_size=1;
|
||||
select @@global.max_binlog_total_size, @@global.binlog_space_limit;
|
||||
set global max_binlog_total_size=1;
|
||||
select @@global.max_binlog_total_size;
|
||||
set global binlog_space_limit=2;
|
||||
select @@global.max_binlog_total_size, @@global.binlog_space_limit;
|
||||
|
||||
--error ER_GLOBAL_VARIABLE
|
||||
set session max_binlog_total_size=1;
|
||||
|
||||
set global max_binlog_total_size=default;
|
||||
|
||||
#
|
||||
# Check permissions
|
||||
#
|
||||
CREATE USER user1@localhost;
|
||||
connect (con2,localhost,user1,,);
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
set global max_binlog_total_size=1;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
set global binlog_space_limit=1;
|
||||
disconnect con2;
|
||||
connection default;
|
||||
DROP USER user1@localhost;
|
278
sql/log.cc
278
sql/log.cc
|
@ -3446,8 +3446,8 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
|
|||
|
||||
MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
|
||||
:reset_master_pending(0), mark_xid_done_waiting(0),
|
||||
bytes_written(0), last_used_log_number(0),
|
||||
file_id(1), open_count(1),
|
||||
bytes_written(0), binlog_space_total(0),
|
||||
last_used_log_number(0), file_id(1), open_count(1),
|
||||
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
||||
num_commits(0), num_group_commits(0),
|
||||
group_commit_trigger_count(0), group_commit_trigger_timeout(0),
|
||||
|
@ -4642,6 +4642,7 @@ err:
|
|||
reset_master_pending--;
|
||||
reset_master_count++;
|
||||
mysql_mutex_unlock(&LOCK_xid_list);
|
||||
binlog_space_total= 0;
|
||||
}
|
||||
|
||||
mysql_mutex_unlock(&LOCK_index);
|
||||
|
@ -4960,7 +4961,6 @@ int MYSQL_BIN_LOG::open_purge_index_file(bool destroy)
|
|||
{
|
||||
int error= 0;
|
||||
File file= -1;
|
||||
|
||||
DBUG_ENTER("MYSQL_BIN_LOG::open_purge_index_file");
|
||||
|
||||
if (destroy)
|
||||
|
@ -5261,8 +5261,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
|
|||
if (unlikely((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/))))
|
||||
goto err;
|
||||
|
||||
while (strcmp(log_file_name, log_info.log_file_name) &&
|
||||
can_purge_log(log_info.log_file_name))
|
||||
while (can_purge_log(log_info.log_file_name))
|
||||
{
|
||||
if (!mysql_file_stat(m_key_file_log,
|
||||
log_info.log_file_name, &stat_area, MYF(0)))
|
||||
|
@ -5300,16 +5299,20 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (stat_area.st_mtime < purge_time)
|
||||
strmake_buf(to_log, log_info.log_file_name);
|
||||
else
|
||||
if (stat_area.st_mtime >= purge_time)
|
||||
break;
|
||||
strmake_buf(to_log, log_info.log_file_name);
|
||||
}
|
||||
if (find_next_log(&log_info, 0))
|
||||
break;
|
||||
}
|
||||
|
||||
error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0);
|
||||
if (to_log[0])
|
||||
{
|
||||
ulonglong reclaimed_space= 0;
|
||||
error= purge_logs(to_log, 1, 0, 1, &reclaimed_space);
|
||||
binlog_space_total-= reclaimed_space;
|
||||
}
|
||||
|
||||
err:
|
||||
mysql_mutex_unlock(&LOCK_index);
|
||||
|
@ -5317,29 +5320,225 @@ err:
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
Purge old logs so that we have a total size lower than binlog_space_limit.
|
||||
|
||||
@note
|
||||
If any of the logs before the deleted one is in use,
|
||||
only purge logs up to this one.
|
||||
|
||||
@retval
|
||||
0 ok
|
||||
@retval
|
||||
LOG_INFO_FATAL if any other than ENOENT error from
|
||||
mysql_file_stat() or mysql_file_delete()
|
||||
*/
|
||||
|
||||
int MYSQL_BIN_LOG::real_purge_logs_by_size(ulonglong binlog_pos)
|
||||
{
|
||||
int error= 0;
|
||||
LOG_INFO log_info;
|
||||
MY_STAT stat_area;
|
||||
char to_log[FN_REFLEN];
|
||||
ulonglong found_space= 0;
|
||||
DBUG_ENTER("real_purge_logs_by_size");
|
||||
|
||||
mysql_mutex_lock(&LOCK_index);
|
||||
|
||||
/* Check if another user changed the value of binlog_space_limit just now */
|
||||
if (! binlog_space_limit)
|
||||
goto err;
|
||||
|
||||
if ((error = find_log_pos(&log_info, NullS,
|
||||
false /*need_lock_index=false*/)))
|
||||
goto err;
|
||||
|
||||
to_log[0] = 0;
|
||||
while (can_purge_log(log_info.log_file_name))
|
||||
{
|
||||
if (!mysql_file_stat(m_key_file_log, log_info.log_file_name, &stat_area,
|
||||
MYF(0)))
|
||||
{
|
||||
if (my_errno != ENOENT)
|
||||
{
|
||||
/*
|
||||
Other than ENOENT are fatal
|
||||
*/
|
||||
THD *thd = current_thd;
|
||||
if (thd)
|
||||
{
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_BINLOG_PURGE_FATAL_ERR,
|
||||
"A problem with getting info on being purged %s; "
|
||||
"consider examining correspondence "
|
||||
"of your binlog index file "
|
||||
"to the actual binlog files",
|
||||
log_info.log_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_warning("Failed to stat log file '%s'",
|
||||
log_info.log_file_name);
|
||||
}
|
||||
error= LOG_INFO_FATAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found_space+= stat_area.st_size;
|
||||
strmake(to_log, log_info.log_file_name, sizeof(to_log) - 1);
|
||||
if (binlog_space_total + binlog_pos - found_space <= binlog_space_limit)
|
||||
break; // Found enough
|
||||
if (find_next_log(&log_info, false /*need_lock_index=false*/))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found_space)
|
||||
{
|
||||
ulonglong reclaimed_space= 0;
|
||||
purge_logs(to_log, true, false /*need_lock_index=false*/,
|
||||
true /*need_update_threads=true*/,
|
||||
&reclaimed_space);
|
||||
DBUG_ASSERT(reclaimed_space == found_space);
|
||||
binlog_space_total-= reclaimed_space;
|
||||
/*
|
||||
The following is here to handle cases where something goes wrong.
|
||||
Like a bug or if somethings adds data to an existing log file.
|
||||
*/
|
||||
DBUG_ASSERT((longlong) binlog_space_total >= 0);
|
||||
if ((longlong) binlog_space_total <= 0)
|
||||
count_binlog_space();
|
||||
}
|
||||
|
||||
err:
|
||||
mysql_mutex_unlock(&LOCK_index);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
/*
|
||||
The following variables are here to allows us to quickly check if
|
||||
the can_purge_log(log_file_name_arg) name will fail in the
|
||||
'log_in_use' call.
|
||||
|
||||
waiting_for_slave_to_change_binlog is 1 if last log_in_use failed.
|
||||
purge_binlog_name is the last failed log_file_name_arg.
|
||||
|
||||
sending_new_binlog_file, cached in purge_sending_new_binlog_file,
|
||||
is incremented every time a slave changes to use a new binary log.
|
||||
*/
|
||||
|
||||
static bool waiting_for_slave_to_change_binlog= 0;
|
||||
static ulonglong purge_sending_new_binlog_file= 0;
|
||||
static char purge_binlog_name[FN_REFLEN];
|
||||
|
||||
bool
|
||||
MYSQL_BIN_LOG::can_purge_log(const char *log_file_name_arg)
|
||||
{
|
||||
xid_count_per_binlog *b;
|
||||
THD *thd= current_thd; // May be NULL at startup
|
||||
bool res;
|
||||
|
||||
if (is_active(log_file_name_arg))
|
||||
return false;
|
||||
mysql_mutex_lock(&LOCK_xid_list);
|
||||
if (is_active(log_file_name_arg) ||
|
||||
(!is_relay_log && waiting_for_slave_to_change_binlog &&
|
||||
purge_sending_new_binlog_file == sending_new_binlog_file &&
|
||||
!strcmp(log_file_name_arg, purge_binlog_name)))
|
||||
return false;
|
||||
|
||||
DBUG_ASSERT(!is_relay_log || binlog_xid_count_list.is_empty());
|
||||
if (!is_relay_log)
|
||||
{
|
||||
I_List_iterator<xid_count_per_binlog> it(binlog_xid_count_list);
|
||||
while ((b= it++) &&
|
||||
0 != strncmp(log_file_name_arg+dirname_length(log_file_name_arg),
|
||||
b->binlog_name, b->binlog_name_len))
|
||||
;
|
||||
xid_count_per_binlog *b;
|
||||
mysql_mutex_lock(&LOCK_xid_list);
|
||||
{
|
||||
I_List_iterator<xid_count_per_binlog> it(binlog_xid_count_list);
|
||||
while ((b= it++) &&
|
||||
0 != strncmp(log_file_name_arg+dirname_length(log_file_name_arg),
|
||||
b->binlog_name, b->binlog_name_len))
|
||||
;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_xid_list);
|
||||
if (b)
|
||||
return false;
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_xid_list);
|
||||
if (b)
|
||||
return false;
|
||||
return !log_in_use(log_file_name_arg);
|
||||
|
||||
if (!is_relay_log)
|
||||
{
|
||||
waiting_for_slave_to_change_binlog= 0;
|
||||
purge_sending_new_binlog_file= sending_new_binlog_file;
|
||||
}
|
||||
if ((res= log_in_use(log_file_name_arg,
|
||||
(is_relay_log ||
|
||||
(thd && thd->lex->sql_command == SQLCOM_PURGE)) ?
|
||||
0 : slave_connections_needed_for_purge)))
|
||||
{
|
||||
if (!is_relay_log)
|
||||
{
|
||||
waiting_for_slave_to_change_binlog= 1;
|
||||
strmake(purge_binlog_name, log_file_name_arg,
|
||||
sizeof(purge_binlog_name)-1);
|
||||
}
|
||||
}
|
||||
return !res;
|
||||
}
|
||||
#endif /* HAVE_REPLICATION */
|
||||
|
||||
|
||||
/**
|
||||
Count a total size of binary logs (except the active one) to the variable
|
||||
binlog_space_total.
|
||||
|
||||
@retval
|
||||
0 ok
|
||||
@retval
|
||||
LOG_INFO_FATAL if any other than ENOENT error from
|
||||
mysql_file_stat() or mysql_file_delete()
|
||||
*/
|
||||
|
||||
int MYSQL_BIN_LOG::count_binlog_space()
|
||||
{
|
||||
int error;
|
||||
LOG_INFO log_info;
|
||||
DBUG_ENTER("count_binlog_space");
|
||||
|
||||
binlog_space_total = 0;
|
||||
if ((error= find_log_pos(&log_info, NullS, false /*need_lock_index=false*/)))
|
||||
goto done;
|
||||
|
||||
MY_STAT stat_area;
|
||||
while (!is_active(log_info.log_file_name))
|
||||
{
|
||||
if (!mysql_file_stat(m_key_file_log, log_info.log_file_name, &stat_area,
|
||||
MYF(0)))
|
||||
{
|
||||
if (my_errno != ENOENT)
|
||||
{
|
||||
error= LOG_INFO_FATAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
binlog_space_total+= stat_area.st_size;
|
||||
if (find_next_log(&log_info, false /*need_lock_index=false*/))
|
||||
break;
|
||||
}
|
||||
done:
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
ulonglong MYSQL_BIN_LOG::get_binlog_space_total()
|
||||
{
|
||||
ulonglong used_space= 0;
|
||||
mysql_mutex_lock(&LOCK_log);
|
||||
/* Get position in current log file */
|
||||
used_space= my_b_tell(&log_file);
|
||||
mysql_mutex_lock(&LOCK_index);
|
||||
mysql_mutex_unlock(&LOCK_log);
|
||||
used_space+= binlog_space_total;
|
||||
mysql_mutex_unlock(&LOCK_index);
|
||||
return used_space;
|
||||
}
|
||||
|
||||
bool
|
||||
MYSQL_BIN_LOG::is_xidlist_idle()
|
||||
{
|
||||
|
@ -5448,6 +5647,7 @@ int MYSQL_BIN_LOG::new_file_without_locking()
|
|||
|
||||
@note
|
||||
The new file name is stored last in the index file
|
||||
binlog_space_total will be updated if binlog_space_limit is set
|
||||
*/
|
||||
|
||||
int MYSQL_BIN_LOG::new_file_impl()
|
||||
|
@ -5529,7 +5729,6 @@ int MYSQL_BIN_LOG::new_file_impl()
|
|||
goto end;
|
||||
}
|
||||
update_binlog_end_pos();
|
||||
|
||||
old_name=name;
|
||||
name=0; // Don't free name
|
||||
close_flag= LOG_CLOSE_TO_BE_OPENED | LOG_CLOSE_INDEX;
|
||||
|
@ -5544,6 +5743,8 @@ int MYSQL_BIN_LOG::new_file_impl()
|
|||
old_file= log_file.file;
|
||||
close_flag|= LOG_CLOSE_DELAYED_CLOSE;
|
||||
delay_close= true;
|
||||
if (binlog_space_limit)
|
||||
binlog_space_total+= binlog_end_pos;
|
||||
}
|
||||
close(close_flag);
|
||||
if (checksum_alg_reset != BINLOG_CHECKSUM_ALG_UNDEF)
|
||||
|
@ -6384,6 +6585,7 @@ int binlog_flush_pending_rows_event(THD *thd, bool stmt_end,
|
|||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function removes the pending rows event, discarding any outstanding
|
||||
rows. If there is no pending rows event available, this is effectively a
|
||||
|
@ -7326,6 +7528,7 @@ MYSQL_BIN_LOG::do_checkpoint_request(ulong binlog_id)
|
|||
int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
|
||||
{
|
||||
int error= 0;
|
||||
ulonglong binlog_pos;
|
||||
DBUG_ENTER("MYSQL_BIN_LOG::rotate");
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
|
@ -7341,7 +7544,8 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
|
|||
//todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log);
|
||||
*check_purge= false;
|
||||
|
||||
if (force_rotate || (my_b_tell(&log_file) >= (my_off_t) max_size))
|
||||
binlog_pos= my_b_tell(&log_file);
|
||||
if (force_rotate || binlog_pos >= max_size)
|
||||
{
|
||||
ulong binlog_id= current_binlog_id;
|
||||
/*
|
||||
|
@ -7383,18 +7587,31 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
|
|||
mark_xid_done(binlog_id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
*check_purge= true;
|
||||
binlog_pos= my_b_tell(&log_file);
|
||||
}
|
||||
}
|
||||
/*
|
||||
Purge by size here for every write. Purge based on timestamps is done
|
||||
by purge() when rotate has been done().
|
||||
*/
|
||||
#ifdef HAVE_REPLICATION
|
||||
purge_logs_by_size(binlog_pos);
|
||||
#endif
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
/**
|
||||
The method executes logs purging routine.
|
||||
|
||||
@param all If false, purge only based on binlog_expire_logs_seconds.
|
||||
If true, purge also based on binlog_space_limit.
|
||||
@retval
|
||||
nonzero - error in rotating routine.
|
||||
*/
|
||||
void MYSQL_BIN_LOG::purge()
|
||||
|
||||
void MYSQL_BIN_LOG::purge(bool all)
|
||||
{
|
||||
mysql_mutex_assert_not_owner(&LOCK_log);
|
||||
#ifdef HAVE_REPLICATION
|
||||
|
@ -7409,14 +7626,21 @@ void MYSQL_BIN_LOG::purge()
|
|||
}
|
||||
DEBUG_SYNC(current_thd, "after_purge_logs_before_date");
|
||||
}
|
||||
if (all && binlog_space_limit)
|
||||
{
|
||||
ulonglong binlog_pos;
|
||||
mysql_mutex_lock(&LOCK_log);
|
||||
binlog_pos= my_b_tell(&log_file);
|
||||
purge_logs_by_size(binlog_pos);
|
||||
mysql_mutex_unlock(&LOCK_log);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void MYSQL_BIN_LOG::checkpoint_and_purge(ulong binlog_id)
|
||||
{
|
||||
do_checkpoint_request(binlog_id);
|
||||
purge();
|
||||
purge(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
19
sql/log.h
19
sql/log.h
|
@ -669,6 +669,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
|
|||
mysql_cond_t COND_xid_list;
|
||||
mysql_cond_t COND_relay_log_updated, COND_bin_log_updated;
|
||||
ulonglong bytes_written;
|
||||
ulonglong binlog_space_total;
|
||||
IO_CACHE index_file;
|
||||
char index_file_name[FN_REFLEN];
|
||||
/*
|
||||
|
@ -746,7 +747,6 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
|
|||
*/
|
||||
int new_file_impl();
|
||||
void do_checkpoint_request(ulong binlog_id);
|
||||
void purge();
|
||||
int write_transaction_or_stmt(group_commit_entry *entry, uint64 commit_id);
|
||||
int queue_for_group_commit(group_commit_entry *entry);
|
||||
bool write_transaction_to_binlog_events(group_commit_entry *entry);
|
||||
|
@ -755,6 +755,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
|
|||
void update_gtid_index(uint32 offset, rpl_gtid gtid);
|
||||
|
||||
public:
|
||||
void purge(bool all);
|
||||
int new_file_without_locking();
|
||||
/*
|
||||
A list of struct xid_count_per_binlog is used to keep track of how many
|
||||
|
@ -1047,6 +1048,22 @@ public:
|
|||
ulonglong *decrease_log_space);
|
||||
int purge_logs_before_date(time_t purge_time);
|
||||
int purge_first_log(Relay_log_info* rli, bool included);
|
||||
int count_binlog_space();
|
||||
void count_binlog_space_with_mutex()
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_index);
|
||||
count_binlog_space();
|
||||
mysql_mutex_unlock(&LOCK_index);
|
||||
}
|
||||
ulonglong get_binlog_space_total();
|
||||
int real_purge_logs_by_size(ulonglong binlog_pos);
|
||||
inline int purge_logs_by_size(ulonglong binlog_pos)
|
||||
{
|
||||
if (is_relay_log || ! binlog_space_limit ||
|
||||
binlog_space_total + binlog_pos <= binlog_space_limit)
|
||||
return 0;
|
||||
return real_purge_logs_by_size(binlog_pos);
|
||||
}
|
||||
int set_purge_index_file_name(const char *base_file_name);
|
||||
int open_purge_index_file(bool destroy);
|
||||
bool truncate_and_remove_binlogs(const char *truncate_file,
|
||||
|
|
|
@ -458,6 +458,11 @@ ulong tc_heuristic_recover= 0;
|
|||
Atomic_counter<uint32_t> THD_count::count, CONNECT::count;
|
||||
bool shutdown_wait_for_slaves;
|
||||
Atomic_counter<uint32_t> slave_open_temp_tables;
|
||||
/*
|
||||
This is incremented every time a slave starts to read a new binary log
|
||||
file. Used by MYSQL_BIN_LOG::can_purge_log()
|
||||
*/
|
||||
Atomic_counter<ulonglong> sending_new_binlog_file;
|
||||
ulong thread_created;
|
||||
ulong back_log, connect_timeout, server_id;
|
||||
ulong what_to_log;
|
||||
|
@ -473,7 +478,10 @@ ulonglong slave_type_conversions_options;
|
|||
ulong thread_cache_size=0;
|
||||
ulonglong binlog_cache_size=0;
|
||||
ulonglong binlog_file_cache_size=0;
|
||||
uint slave_connections_needed_for_purge;
|
||||
ulonglong max_binlog_cache_size=0;
|
||||
ulonglong internal_binlog_space_limit;
|
||||
uint internal_slave_connections_needed_for_purge;
|
||||
ulong slave_max_allowed_packet= 0;
|
||||
double slave_max_statement_time_double;
|
||||
ulonglong slave_max_statement_time;
|
||||
|
@ -533,6 +541,7 @@ uint sync_binlog_period= 0, sync_relaylog_period= 0,
|
|||
sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
|
||||
double expire_logs_days = 0;
|
||||
ulong binlog_expire_logs_seconds = 0;
|
||||
ulonglong binlog_space_limit;
|
||||
|
||||
/**
|
||||
Soft upper limit for number of sp_head objects that can be stored
|
||||
|
@ -5426,20 +5435,25 @@ static int init_server_components()
|
|||
}
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
binlog_space_limit= internal_binlog_space_limit;
|
||||
slave_connections_needed_for_purge=
|
||||
internal_slave_connections_needed_for_purge;
|
||||
|
||||
if (opt_bin_log)
|
||||
{
|
||||
if (binlog_expire_logs_seconds)
|
||||
{
|
||||
time_t purge_time= server_start_time - binlog_expire_logs_seconds;
|
||||
if (purge_time >= 0)
|
||||
mysql_bin_log.purge_logs_before_date(purge_time);
|
||||
}
|
||||
if (binlog_space_limit)
|
||||
mysql_bin_log.count_binlog_space_with_mutex();
|
||||
mysql_bin_log.purge(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (binlog_expire_logs_seconds && (global_system_variables.log_warnings >= 4))
|
||||
sql_print_information("You need to use --log-bin to make --expire-logs-days "
|
||||
"or --binlog-expire-logs-seconds work.");
|
||||
if ((binlog_expire_logs_seconds || binlog_space_limit) &&
|
||||
(global_system_variables.log_warnings >= 4))
|
||||
sql_print_information("You need to use --log-bin to make "
|
||||
"--expire-logs-days, "
|
||||
"--binlog-expire-logs-seconds or "
|
||||
"--max-binlog-total-size "
|
||||
"work.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -7235,6 +7249,20 @@ static int show_memory_used(THD *thd, SHOW_VAR *var, char *buff,
|
|||
}
|
||||
|
||||
|
||||
static int show_binlog_space_total(THD *thd, SHOW_VAR *var, char *buff,
|
||||
struct system_status_var *status_var,
|
||||
enum enum_var_type scope)
|
||||
{
|
||||
var->type= SHOW_LONGLONG;
|
||||
var->value= buff;
|
||||
if (opt_bin_log && binlog_space_limit)
|
||||
*(ulonglong*) buff= mysql_bin_log.get_binlog_space_total();
|
||||
else
|
||||
*(ulonglong*) buff= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
static int debug_status_func(THD *thd, SHOW_VAR *var, void *buff,
|
||||
system_status_var *, enum_var_type)
|
||||
|
@ -7321,6 +7349,7 @@ SHOW_VAR status_vars[]= {
|
|||
{"Binlog_gtid_index_miss", (char*) &binlog_gtid_index_miss, SHOW_LONG},
|
||||
{"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use, SHOW_LONG},
|
||||
{"Binlog_stmt_cache_use", (char*) &binlog_stmt_cache_use, SHOW_LONG},
|
||||
{"Binlog_disk_use", (char*) &show_binlog_space_total, SHOW_SIMPLE_FUNC},
|
||||
{"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
|
||||
{"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
|
||||
{"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
|
||||
|
|
|
@ -158,6 +158,7 @@ extern bool opt_using_transactions;
|
|||
extern ulong current_pid;
|
||||
extern double expire_logs_days;
|
||||
extern ulong binlog_expire_logs_seconds;
|
||||
extern ulonglong binlog_space_limit;
|
||||
extern my_bool relay_log_recovery;
|
||||
extern uint sync_binlog_period, sync_relaylog_period,
|
||||
sync_relayloginfo_period, sync_masterinfo_period;
|
||||
|
@ -224,6 +225,8 @@ extern ulong delayed_insert_limit, delayed_queue_size;
|
|||
extern ulong delayed_insert_threads, delayed_insert_writes;
|
||||
extern ulong delayed_rows_in_use,delayed_insert_errors;
|
||||
extern Atomic_counter<uint32_t> slave_open_temp_tables;
|
||||
extern Atomic_counter<ulonglong> sending_new_binlog_file;
|
||||
extern uint slave_connections_needed_for_purge;
|
||||
extern ulonglong query_cache_size;
|
||||
extern ulong query_cache_limit;
|
||||
extern ulong query_cache_min_res_unit;
|
||||
|
@ -244,6 +247,8 @@ extern uint max_prepared_stmt_count, prepared_stmt_count;
|
|||
extern MYSQL_PLUGIN_IMPORT ulong open_files_limit;
|
||||
extern ulonglong binlog_cache_size, binlog_stmt_cache_size, binlog_file_cache_size;
|
||||
extern ulonglong max_binlog_cache_size, max_binlog_stmt_cache_size;
|
||||
extern ulonglong internal_binlog_space_limit;
|
||||
extern uint internal_slave_connections_needed_for_purge;
|
||||
extern ulong max_binlog_size;
|
||||
extern ulong slave_max_allowed_packet;
|
||||
extern ulonglong slave_max_statement_time;
|
||||
|
|
|
@ -587,22 +587,42 @@ void adjust_linfo_offsets(my_off_t purge_offset)
|
|||
}
|
||||
|
||||
|
||||
static my_bool log_in_use_callback(THD *thd, const char *log_name)
|
||||
struct st_log_in_use
|
||||
{
|
||||
const char *log_name;
|
||||
uint connected_slaves;
|
||||
};
|
||||
|
||||
static my_bool log_in_use_callback(THD *thd, st_log_in_use *arg)
|
||||
{
|
||||
my_bool result= 0;
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
if (auto linfo= thd->current_linfo)
|
||||
result= !strcmp(log_name, linfo->log_file_name);
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
const char *log_name= arg->log_name;
|
||||
if (thd->current_linfo)
|
||||
{
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
if (LOG_INFO *linfo= thd->current_linfo)
|
||||
{
|
||||
result= !strcmp(log_name, linfo->log_file_name);
|
||||
if (linfo->log_file_name[0]) // If slave is active
|
||||
arg->connected_slaves++;
|
||||
}
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool log_in_use(const char* log_name)
|
||||
bool log_in_use(const char* log_name, uint min_connected)
|
||||
{
|
||||
return server_threads.iterate(log_in_use_callback, log_name);
|
||||
st_log_in_use arg;
|
||||
arg.log_name= log_name;
|
||||
arg.connected_slaves= 0;
|
||||
|
||||
return ((server_threads.iterate(log_in_use_callback, &arg) ||
|
||||
arg.connected_slaves < min_connected));
|
||||
}
|
||||
|
||||
|
||||
bool purge_error_message(THD* thd, int res)
|
||||
{
|
||||
uint errcode;
|
||||
|
@ -2997,6 +3017,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
|
|||
* return 0 - OK
|
||||
* 1 - NOK
|
||||
*/
|
||||
|
||||
static int send_one_binlog_file(binlog_send_info *info,
|
||||
IO_CACHE* log,
|
||||
LOG_INFO* linfo,
|
||||
|
@ -3011,6 +3032,8 @@ static int send_one_binlog_file(binlog_send_info *info,
|
|||
linfo->pos= start_pos;
|
||||
}
|
||||
|
||||
/* Counter used by can_purge_log() */
|
||||
sending_new_binlog_file++;
|
||||
while (!should_stop(info))
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -38,7 +38,7 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len,
|
|||
ulong next_log_number);
|
||||
bool purge_master_logs(THD* thd, const char* to_log);
|
||||
bool purge_master_logs_before_date(THD* thd, time_t purge_time);
|
||||
bool log_in_use(const char* log_name);
|
||||
bool log_in_use(const char* log_name, uint min_connections);
|
||||
void adjust_linfo_offsets(my_off_t purge_offset);
|
||||
void show_binlogs_get_fields(THD *thd, List<Item> *field_list);
|
||||
bool show_binlogs(THD* thd);
|
||||
|
|
|
@ -1247,6 +1247,68 @@ Sys_binlog_expire_logs_seconds(
|
|||
VALID_RANGE(0, 8553600), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD,
|
||||
NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(copy_to_expire_logs_days));
|
||||
|
||||
|
||||
static bool update_binlog_space_limit(sys_var *, THD *,
|
||||
enum_var_type type)
|
||||
{
|
||||
#ifdef HAVE_REPLICATION
|
||||
/* Refresh summary of binlog sizes */
|
||||
mysql_bin_log.lock_index();
|
||||
binlog_space_limit= internal_binlog_space_limit;
|
||||
slave_connections_needed_for_purge=
|
||||
internal_slave_connections_needed_for_purge;
|
||||
|
||||
if (opt_bin_log)
|
||||
{
|
||||
if (binlog_space_limit)
|
||||
mysql_bin_log.count_binlog_space();
|
||||
/* Inform can_purge_log() that it should do a recheck of log_in_use() */
|
||||
sending_new_binlog_file++;
|
||||
mysql_bin_log.unlock_index();
|
||||
mysql_bin_log.purge(1);
|
||||
return 0;
|
||||
}
|
||||
mysql_bin_log.unlock_index();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Sys_var_on_access_global<Sys_var_ulonglong,
|
||||
PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_BINLOG_CACHE_SIZE>
|
||||
Sys_max_binlog_total_size(
|
||||
"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",
|
||||
GLOBAL_VAR(internal_binlog_space_limit), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, ULONGLONG_MAX), DEFAULT(0), BLOCK_SIZE(1),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
|
||||
ON_UPDATE(update_binlog_space_limit));
|
||||
|
||||
static Sys_var_on_access_global<Sys_var_ulonglong,
|
||||
PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_BINLOG_CACHE_SIZE>
|
||||
Sys_binlog_space_limit(
|
||||
"binlog_space_limit",
|
||||
"Alias for max_binlog_total_size. Compatibility with Percona server.",
|
||||
GLOBAL_VAR(internal_binlog_space_limit), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, ULONGLONG_MAX), DEFAULT(0), BLOCK_SIZE(1),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
|
||||
ON_UPDATE(update_binlog_space_limit));
|
||||
|
||||
static Sys_var_on_access_global<Sys_var_uint,
|
||||
PRIV_SET_SYSTEM_GLOBAL_VAR_MAX_BINLOG_CACHE_SIZE>
|
||||
Sys_slave_connections_needed_for_purge(
|
||||
"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.",
|
||||
GLOBAL_VAR(internal_slave_connections_needed_for_purge),
|
||||
CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, UINT_MAX), DEFAULT(1), BLOCK_SIZE(1),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
|
||||
ON_UPDATE(update_binlog_space_limit));
|
||||
|
||||
static Sys_var_mybool Sys_flush(
|
||||
"flush", "Flush MyISAM tables to disk between SQL commands",
|
||||
GLOBAL_VAR(myisam_flush),
|
||||
|
|
Loading…
Add table
Reference in a new issue