Fix binary log retention limit on MariaDB

This commit is contained in:
Ilia Ross
2026-08-28 02:46:40 +02:00
parent b3b81af34f
commit 4e6ba5229e
6 changed files with 43 additions and 9 deletions

View File

@@ -8,11 +8,12 @@ point-in-time recovery of backups. <p>
When binary logging is enabled, log files are written under the configured
base name and grow as changes are made. To stop them from filling up the disk,
a retention period can be set after which old logs are automatically deleted,
or old logs can be deleted immediately using the form at the bottom of the
page. <p>
or old logs can be deleted immediately on the <b>Delete Logs</b> tab. The
button at the bottom of the page closes the current log and starts a new one,
giving backups and log deletion a clean boundary. <p>
For any changes on this page to take effect, the MySQL server must be
re-started, either with the <b>Save and Restart MySQL</b> button or using the
buttons on the module's main page. <p>
Configuration changes only take effect once the MySQL server is re-started,
either with the <b>Save and Restart MySQL</b> button or using the buttons on
the module's main page. Deleting and rotating logs happen immediately. <p>
<footer>

View File

@@ -5,3 +5,8 @@ them automatically. Without a limit, logs will grow until they fill up the
disk. For point-in-time recovery the retention period must be at least as long
as the interval between full backups, so that all transactions since the last
backup remain available for replay.</p>
<p>A value of <tt>0</tt> disables automatic deletion entirely. Fractions of a
day like <tt>0.5</tt> are supported on MySQL 8 and MariaDB 10.6 or later.
MariaDB always limits retention to 99 days, while MySQL 8 accepts up to
49710 days.</p>

View File

@@ -3,4 +3,4 @@
<p>When a binary log file reaches this size, the server closes it and starts
writing a new one. Smaller files make deleting old logs and point-in-time
recovery more granular, at the cost of more files. The server accepts sizes
between 4 kB and 1 GB, which is also the default.</p>
between 4 kB and 1 GB, and defaults to the 1 GB maximum.</p>

View File

@@ -1288,6 +1288,17 @@ my ($days) = @_;
return int($days * 86400 + 0.5);
}
# get_binlog_expire_max([variant])
# Returns the maximum retention in seconds that this or the given database
# variant accepts, which is 99 days on MariaDB but the full 32-bit range
# on MySQL
sub get_binlog_expire_max
{
my ($variant) = @_;
($variant) = (&get_mysql_variant_cached())[1] if (!$variant);
return $variant eq "mariadb" ? 8553600 : 4294967295;
}
# get_mysql_variant_cached()
# Like get_remote_mysql_variant, but falls back to the version detected at
# module setup time when the server cannot be queried, such as when it is

View File

@@ -123,11 +123,13 @@ else {
&error($text{'binlogs_eexpire'});
my $days = $in{'expire'} + 0;
if ($newexpire) {
# The seconds variable is limited to 32 bits
# The seconds variable is limited to 99 days on MariaDB, and
# to 32 bits on MySQL
my $secs = &parse_binlog_expire_days($days);
$secs <= 4294967295 ||
my $max = &get_binlog_expire_max($variant);
$secs <= $max ||
&error(&text('binlogs_eexpiremax',
&format_binlog_expire_days(4294967295)));
&format_binlog_expire_days($max)));
&save_directive($conf, $mysqld, "expire_logs_days", [ ]);
&save_directive($conf, $mysqld, "binlog_expire_logs_seconds",
[ $secs ]);

View File

@@ -138,4 +138,19 @@ subtest 'binary log retention limit covers the full 32-bit range' => sub {
'whole days below the maximum stay within the limit');
};
subtest 'retention maximum is variant specific' => sub {
is(main::get_binlog_expire_max('mysql'), 4294967295,
'MySQL accepts the full 32-bit seconds range');
is(main::get_binlog_expire_max('mariadb'), 8553600,
'MariaDB is limited to 99 days of seconds');
is(main::parse_binlog_expire_days(99),
main::get_binlog_expire_max('mariadb'),
'exactly 99 days is accepted on MariaDB');
cmp_ok(main::parse_binlog_expire_days('99.000012'), '>',
main::get_binlog_expire_max('mariadb'),
'just over 99 days exceeds the MariaDB limit');
is(main::format_binlog_expire_days(8553600), '99',
'the MariaDB maximum displays as 99 days');
};
done_testing();