Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-25607

Auto-generated DELETE from HEAP table can break replication

Details

    Description

      After server restart, a DELETE query is written into the binary log for every HEAP table to reflect the restart emptying them. It is written unconditionally, regardless whether it's actually executable or not. If it is not, it causes replication abort.

      In the example test case below DELETE causes an error because the table has a DELETE trigger which refers to a non-existing table.

      --source include/master-slave.inc
       
      reset master;
       
      create table t (a int) engine=MEMORY;
      create trigger tr after delete on t for each row update t2 set a = 1;
      insert into t values (1);
       
      --let $rpl_server_number= 1
      --source include/rpl_restart_server.inc
       
      check table t;
       
      --sync_slave_with_master
       
      # Cleanup
      --connection master
      drop table t;
      --source include/rpl_end.inc
      

      10.2 e788738e

      master-bin.000002	4	Format_desc	1	256	Server ver: 10.2.38-MariaDB-debug-log, Binlog ver: 4
      master-bin.000002	256	Gtid_list	1	299	[0-1-3]
      master-bin.000002	299	Binlog_checkpoint	1	343	master-bin.000002
      master-bin.000002	343	Gtid	1	385	GTID 0-1-4
      master-bin.000002	385	Query	1	474	DELETE FROM `test`.`t`
      

      Last_Errno	1146
      Last_Error	Error 'Table 'test.t2' doesn't exist' on query. Default database: 'test'. Query: 'DELETE FROM `test`.`t`'
      

      Attachments

        Issue Links

          Activity

            knielsen, do you think this change could cause any problems?

            serg Sergei Golubchik added a comment - knielsen , do you think this change could cause any problems?

            I agree with the patch that using TRUNCATE is more appropriate than DELETE. The truncate more closely represents the operation that (implicitly) occured on the master on the HEAP table due to the restart. DELETE triggers were not run on the master, so they mustn't be run on the slave either. The test case is for an invalid trigger that causes an error, but the more natural case of a "real" trigger would similarly cause the slave to diverge.

            I don't think this patch will make HEAP tables work well for replication. Ok, so now a master restart will propagate the loss of table rows to the slave (assuming there isn't another corner case that's overlooked). But if the slave restarts, the replication still diverges.

            Anyway, this special case for binlogging row deletion for HEAP table at server start seems to be ancient code, and using TRUNCATE instead of DELETE shouldn't make things worse, at least, so I don't see any problems.

            - Kristian.

            knielsen Kristian Nielsen added a comment - I agree with the patch that using TRUNCATE is more appropriate than DELETE. The truncate more closely represents the operation that (implicitly) occured on the master on the HEAP table due to the restart. DELETE triggers were not run on the master, so they mustn't be run on the slave either. The test case is for an invalid trigger that causes an error, but the more natural case of a "real" trigger would similarly cause the slave to diverge. I don't think this patch will make HEAP tables work well for replication. Ok, so now a master restart will propagate the loss of table rows to the slave (assuming there isn't another corner case that's overlooked). But if the slave restarts, the replication still diverges. Anyway, this special case for binlogging row deletion for HEAP table at server start seems to be ancient code, and using TRUNCATE instead of DELETE shouldn't make things worse, at least, so I don't see any problems. - Kristian.
            Elkin Andrei Elkin added a comment -

            > if the slave restarts...

            A good point.
            To that matter I'd consider a partial backup from master for all non-durable tables (except of course those that \in replicate_ignore_*).
            The partial backup for a memory table could be implemented as INSERT..SELECT ROW-format events generated by master and sent to slave at its connecting time for pre-processing before any first replicated event on top of the backup image has arrived.

            Elkin Andrei Elkin added a comment - > if the slave restarts... A good point. To that matter I'd consider a partial backup from master for all non-durable tables (except of course those that \in replicate_ignore_* ). The partial backup for a memory table could be implemented as INSERT..SELECT ROW-format events generated by master and sent to slave at its connecting time for pre-processing before any first replicated event on top of the backup image has arrived.
            Elkin Andrei Elkin added a comment -

            Approved.

            Elkin Andrei Elkin added a comment - Approved.

            Pushed into 10.5 as cbc1898e82b.

            Merge conflict observed in 10.6 with fix: 10.6-MDEV-25607-mergefix

            bnestere Brandon Nesterenko added a comment - Pushed into 10.5 as cbc1898e82b . Merge conflict observed in 10.6 with fix: 10.6-MDEV-25607-mergefix

            People

              bnestere Brandon Nesterenko
              elenst Elena Stepanova
              Votes:
              1 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.