Details
-
Bug
-
Status: Open (View Workflow)
-
Minor
-
Resolution: Unresolved
-
None
-
None
Description
If there is any changes to the temporary table that is not binlogged, the table is marked as not up to date.
It does not survive DDL that rebuilds the table. ALTER … ADD COLUMN, ALTER … FORCE and OPTIMIZE go through the create path, which sets table_creation_was_logged = 1 again. The server then believes the replica's copy is current and replicates later statements verbatim against it — diverging a permanent base table with no error and a healthy applier.
ALTER … FORCE is the decisive case: no schema change at all, purely a rebuild, and the state is still lost. ANALYZE and TRUNCATE don't rebuild, keep the state, and converge — the controls.
master test.base: (1,510) (2,20) (3,30)
replica test.base: (1,10) (2,20) (3,30)
Slave_SQL_Running = Yes, Last_SQL_Errno = 0
# THIS TEST FAILS ON UNFIXED SERVERS at the first diff_tables, and passes once |
# the state is preserved across a rebuild. |
--source include/have_innodb.inc
|
--source include/master-slave.inc
|
|
|
--connection master
|
--disable_query_log
|
CALL mtr.add_suppression("Unsafe statement written to the binary log"); |
--enable_query_log
|
|
|
SET SESSION binlog_format= STATEMENT; |
SELECT @@session.create_tmp_table_binlog_formats; |
CREATE TABLE base (id INT PRIMARY KEY, v INT) ENGINE=InnoDB; |
--sync_slave_with_master
|
|
|
--echo #
|
--echo # ======== ALTER ... FORCE -- a pure rebuild, no schema change
|
--echo #
|
--connection master
|
CREATE TEMPORARY TABLE t (id INT PRIMARY KEY, v INT UNIQUE) ENGINE=InnoDB; |
CREATE TEMPORARY TABLE x (id INT PRIMARY KEY, v INT) ENGINE=InnoDB; |
INSERT INTO t VALUES (1,10),(2,20),(3,30); |
INSERT INTO x VALUES (1,1),(2,2),(3,3); |
|
|
--echo # A failing multi-table UPDATE marks t as not up to date.
|
--error ER_DUP_ENTRY
|
UPDATE t, x SET t.v = 10, x.v = x.v + 1 WHERE t.id = x.id; |
|
|
--echo # This change is correctly NOT binlogged, so the replica's copy of t is
|
--echo # now stale. That is expected and safe on its own.
|
UPDATE t SET v = v + 500 WHERE id = 1; |
|
|
--echo # The statement under test: a pure rebuild.
|
ALTER TABLE t FORCE; |
|
|
--echo # Propagate t into the permanent base table.
|
--echo # If t is still marked not up to date, this is row-logged and base
|
--echo # converges. If the rebuild reset the state, it is statement-logged
|
--echo # against the replica's stale copy and base diverges.
|
INSERT INTO base SELECT id, v FROM t; |
|
|
--echo # master's view
|
--sorted_result
|
SELECT * FROM base; |
|
|
--sync_slave_with_master
|
--source include/check_slave_no_error.inc
|
--echo # replica's view of the same permanent table
|
--connection slave
|
--sorted_result
|
SELECT * FROM base; |
|
|
--connection master
|
--let $diff_tables= master:test.base, slave:test.base
|
--source include/diff_tables.inc
|
--echo # ==> base converged after ALTER ... FORCE
|
|
|
--connection master
|
DROP TEMPORARY TABLE t, x; |
DELETE FROM base; |
--sync_slave_with_master
|
|
|
--echo #
|
--echo # ======== control: ANALYZE does not rebuild, so the state survives
|
--echo #
|
--connection master
|
CREATE TEMPORARY TABLE t (id INT PRIMARY KEY, v INT UNIQUE) ENGINE=InnoDB; |
CREATE TEMPORARY TABLE x (id INT PRIMARY KEY, v INT) ENGINE=InnoDB; |
INSERT INTO t VALUES (1,10),(2,20),(3,30); |
INSERT INTO x VALUES (1,1),(2,2),(3,3); |
--error ER_DUP_ENTRY
|
UPDATE t, x SET t.v = 10, x.v = x.v + 1 WHERE t.id = x.id; |
UPDATE t SET v = v + 500 WHERE id = 1; |
|
|
ANALYZE TABLE t; |
|
|
INSERT INTO base SELECT id, v FROM t; |
--sorted_result
|
SELECT * FROM base; |
--sync_slave_with_master
|
--source include/check_slave_no_error.inc
|
--connection master
|
--let $diff_tables= master:test.base, slave:test.base
|
--source include/diff_tables.inc
|
--echo # ==> base converged after ANALYZE, as it must
|
|
|
--connection master
|
DROP TEMPORARY TABLE t, x; |
DROP TABLE base; |
--sync_slave_with_master
|
--source include/rpl_end.inc |