Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
12.3.1
-
None
-
Unexpected results
Description
With binlog-in-engine (BiE), PURGE BINARY LOGS fails when fewer replicas are connected than
slave_connections_needed_for_purge (default 1; documented). Before any purge the error is
ER_LOG_IN_USE (1378). After an earlier purge has removed the oldest file, the failure is
ER_ERROR_ON_READ (1024) naming that already-deleted file. Both cases succeed when
slave_connections_needed_for_purge=0 or when a replica/reader is connected.
How to repeat (MTR test attached):
1. Master and slave with --log-bin --binlog-storage-engine=innodb; slave caught up after 4 x (INSERT; FLUSH BINARY LOGS).
2. PURGE BINARY LOGS TO 'binlog-000002.ibb'; – succeeds, files 0 and 1 removed
3. STOP SLAVE (dump thread gone); 4 more x (INSERT; FLUSH BINARY LOGS).
4. PURGE BINARY LOGS TO 'binlog-000004.ibb';
Actual:
ERROR 1024: Error reading file './binlog-000000.ibb' (errno: 2 "No such file or directory")
Expected: the same ER_LOG_IN_USE (1378) as before the first purge, or at least an error that does not
refer to a file the server has already deleted.
BiE TEST :
--source include/have_binlog_format_row.inc
|
--source include/master-slave.inc
|
--source include/have_innodb_binlog.inc
|
|
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; |
--let $i= 0
|
while ($i < 4)
|
{
|
--eval INSERT INTO t1 VALUES ($i) |
FLUSH BINARY LOGS; |
--inc $i |
}
|
--sync_slave_with_master
|
|
|
--echo #
|
--echo # No replica connected and nothing purged yet: the purge is refused.
|
--echo #
|
--connection slave
|
--source include/stop_slave.inc
|
--connection master
|
# The dump thread can linger after STOP SLAVE; kill it so no replica is connected. |
--let $dump_id= `SELECT id FROM information_schema.processlist WHERE command='Binlog Dump'`
|
--disable_query_log
|
--eval KILL $dump_id
|
--enable_query_log
|
--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE command='Binlog Dump'
|
--source include/wait_condition.inc
|
--error ER_LOG_IN_USE
|
PURGE BINARY LOGS TO 'binlog-000002.ibb'; |
--let $first_log= query_get_value(SHOW BINARY LOGS, Log_name, 1)
|
--echo # oldest binlog file: $first_log
|
|
|
--echo #
|
--echo # Setup: with a replica connected and caught up, purge files 0 and 1.
|
--echo #
|
--connection slave
|
--source include/start_slave.inc
|
--connection master
|
--sync_slave_with_master
|
--connection master
|
--let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist WHERE command='Binlog Dump'
|
--source include/wait_condition.inc
|
PURGE BINARY LOGS TO 'binlog-000002.ibb'; |
|
|
--echo #
|
--echo # No replica connected, after the earlier purge removed file 0: the purge
|
--echo # must be refused with the same ER_LOG_IN_USE. Before the fix it fails with
|
--echo # ER_ERROR_ON_READ (1024), naming binlog-000000.ibb which was already deleted.
|
--echo #
|
--connection slave
|
--source include/stop_slave.inc
|
--connection master
|
--let $dump_id= `SELECT id FROM information_schema.processlist WHERE command='Binlog Dump'`
|
--disable_query_log
|
--eval KILL $dump_id
|
--enable_query_log
|
--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE command='Binlog Dump'
|
--source include/wait_condition.inc
|
--let $i= 10
|
while ($i < 14)
|
{
|
--eval INSERT INTO t1 VALUES ($i) |
FLUSH BINARY LOGS; |
--inc $i |
}
|
--error ER_LOG_IN_USE
|
PURGE BINARY LOGS TO 'binlog-000004.ibb'; |
--let $first_log= query_get_value(SHOW BINARY LOGS, Log_name, 1)
|
--echo # oldest binlog file: $first_log
|
|
|
--echo #
|
--echo # Cleanup
|
--echo #
|
--connection slave
|
--source include/start_slave.inc
|
--connection master
|
DROP TABLE t1; |
--source include/rpl_end.inc |
BiE test output :
mysqltest: query 'PURGE BINARY LOGS TO 'binlog-000004.ibb'' failed with wrong errno
ER_ERROR_ON_READ (1024): 'Error reading file './binlog-000000.ibb' (errno: 2 "No such file or directory")',
instead of ER_LOG_IN_USE (1378)
Legacy binlog behave correctly as attached in the below test :
--source include/have_innodb.inc
|
--source include/have_binlog_format_row.inc
|
--source include/master-slave.inc
|
|
|
# The rpl suite default is 0; use the binlog-in-engine default of 1. |
SET @old_min_slaves= @@GLOBAL.slave_connections_needed_for_purge; |
SET GLOBAL slave_connections_needed_for_purge= 1; |
|
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; |
--let $i= 0
|
while ($i < 4)
|
{
|
--eval INSERT INTO t1 VALUES ($i) |
FLUSH BINARY LOGS; |
--inc $i |
}
|
--sync_slave_with_master
|
|
|
--echo #
|
--echo # With a replica connected and caught up, purge files 1 and 2.
|
--echo #
|
--connection master
|
--let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist WHERE command='Binlog Dump'
|
--source include/wait_condition.inc
|
PURGE BINARY LOGS TO 'master-bin.000003'; |
|
|
--echo #
|
--echo # No replica connected, after the earlier purge: with the legacy binlog the
|
--echo # purge succeeds.
|
--echo #
|
--connection slave
|
--source include/stop_slave.inc
|
--connection master
|
# The dump thread can linger after STOP SLAVE; kill it so no replica is connected. |
--let $dump_id= `SELECT id FROM information_schema.processlist WHERE command='Binlog Dump'`
|
--disable_query_log
|
--eval KILL $dump_id
|
--enable_query_log
|
--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE command='Binlog Dump'
|
--source include/wait_condition.inc
|
--let $i= 10
|
while ($i < 14)
|
{
|
--eval INSERT INTO t1 VALUES ($i) |
FLUSH BINARY LOGS; |
--inc $i |
}
|
PURGE BINARY LOGS TO 'master-bin.000005'; |
--let $first_log= query_get_value(SHOW BINARY LOGS, Log_name, 1)
|
--echo # oldest binlog file: $first_log
|
|
|
--echo #
|
--echo # Cleanup
|
--echo #
|
--connection slave
|
--source include/start_slave.inc
|
--connection master
|
SET GLOBAL slave_connections_needed_for_purge= @old_min_slaves; |
DROP TABLE t1; |
--source include/rpl_end.inc
|
|
|
Result (mysql-test/suite/rpl/r/binlog_purge_replica_gate_legacy.result)
|
|
|
include/master-slave.inc
|
[connection master] |
SET @old_min_slaves= @@GLOBAL.slave_connections_needed_for_purge; |
SET GLOBAL slave_connections_needed_for_purge= 1; |
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; |
INSERT INTO t1 VALUES (0); |
FLUSH BINARY LOGS; |
INSERT INTO t1 VALUES (1); |
FLUSH BINARY LOGS; |
INSERT INTO t1 VALUES (2); |
FLUSH BINARY LOGS; |
INSERT INTO t1 VALUES (3); |
FLUSH BINARY LOGS; |
connection slave; |
#
|
# With a replica connected and caught up, purge files 1 and 2. |
#
|
connection master; |
PURGE BINARY LOGS TO 'master-bin.000003'; |
#
|
# No replica connected, after the earlier purge: with the legacy binlog the |
# purge succeeds.
|
#
|
connection slave; |
include/stop_slave.inc
|
connection master; |
INSERT INTO t1 VALUES (10); |
FLUSH BINARY LOGS; |
INSERT INTO t1 VALUES (11); |
FLUSH BINARY LOGS; |
INSERT INTO t1 VALUES (12); |
FLUSH BINARY LOGS; |
INSERT INTO t1 VALUES (13); |
FLUSH BINARY LOGS; |
PURGE BINARY LOGS TO 'master-bin.000005'; |
# oldest binlog file: master-bin.000005
|
#
|
# Cleanup
|
#
|
connection slave; |
include/start_slave.inc
|
connection master; |
SET GLOBAL slave_connections_needed_for_purge= @old_min_slaves; |
DROP TABLE t1; |
include/rpl_end.inc
|