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

ROW replication continues after a replica-side trigger raises SQLSTATE 45000

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Major
    • Resolution: Unresolved
    • None
    • None
    • Replication
    • None
    • Unexpected results
    • Hide
      MariaDB ROW replication can apply a row through a replica-side trigger that raises SQLSTATE {{45000}} without stopping the replica SQL thread. The same trigger raises error 1644 during an ordinary local INSERT on the replica. Under ROW replication with {{slave_run_triggers_for_rbr=YES}}, the source row is stored on the replica, {{Last_SQL_Error}} remains empty, and {{Slave_SQL_Running}} remains {{Yes}}.
      Show
      MariaDB ROW replication can apply a row through a replica-side trigger that raises SQLSTATE {{45000}} without stopping the replica SQL thread. The same trigger raises error 1644 during an ordinary local INSERT on the replica. Under ROW replication with {{slave_run_triggers_for_rbr=YES}}, the source row is stored on the replica, {{Last_SQL_Error}} remains empty, and {{Slave_SQL_Running}} remains {{Yes}}.

    Description

      Summary

      MariaDB ROW replication can apply a row through a replica-side trigger that
      raises SQLSTATE 45000 without stopping the replica SQL thread. The
      same trigger raises error 1644 during an ordinary local INSERT on the replica.
      Under ROW replication with slave_run_triggers_for_rbr=YES, the source row is
      stored on the replica, Last_SQL_Error remains empty, and
      Slave_SQL_Running remains Yes.

      Environment

      • Product: MariaDB Server
      • Observed versions:
        • MariaDB 12.2.2 primary -> MariaDB 12.2.2 replica
        • MariaDB 10.6 primary -> MariaDB 12.2.2 replica
      • Replication: asynchronous file/position replication
      • Binary logging: binlog_format=ROW
      • Replica trigger mode: slave_run_triggers_for_rbr=YES
      • Storage engine: InnoDB

      Steps to reproduce

      Set up a MariaDB primary and replica using file/position ROW replication.

      Create the same base table on both endpoints. The base table includes a stored
      generated column so the trigger can record the row image it sees:

      CREATE TABLE base_t(
        id INT PRIMARY KEY,
        v INT NOT NULL,
        g INT GENERATED ALWAYS AS (v * 2) STORED,
        note VARCHAR(32) NOT NULL
      ) ENGINE=InnoDB;
      

      On the replica only, create a local audit table and a local AFTER INSERT
      trigger. The trigger raises an error for rows whose note value is
      'fail':

      CREATE TABLE side_audit(
        seq INT AUTO_INCREMENT PRIMARY KEY,
        row_id INT NOT NULL,
        seen_v INT NOT NULL,
        seen_g INT NOT NULL,
        note VARCHAR(32) NOT NULL
      ) ENGINE=InnoDB;
       
      CREATE TRIGGER base_t_ai AFTER INSERT ON base_t
      FOR EACH ROW
      BEGIN
        IF NEW.note = 'fail' THEN
          SIGNAL SQLSTATE '45000'
            SET MESSAGE_TEXT='replica side trigger failure';
        ELSE
          INSERT INTO side_audit(row_id,seen_v,seen_g,note)
          VALUES(NEW.id,NEW.v,NEW.g,NEW.note);
        END IF;
      END;
      

      Enable replica-side trigger execution for row events:

      SET GLOBAL slave_run_triggers_for_rbr='YES';
      

      First verify the local behavior on the replica:

      SET sql_log_bin=0;
      INSERT INTO base_t(id,v,note) VALUES(900,900,'fail');
      

      The ordinary local INSERT on the replica fails:

      ERROR 1644 (45000): replica side trigger failure
      

      After cleaning up the local control row if necessary, insert the failing row on
      the primary and wait until the replica reaches the primary binary log position:

      INSERT INTO base_t(id,v,note) VALUES(1,10,'fail');
      

      Then inspect the replica:

      SHOW SLAVE STATUS\G
      SELECT id,v,g,note FROM base_t ORDER BY id;
      SELECT row_id,seen_v,seen_g,note FROM side_audit ORDER BY seq;
      

      Expected result

      Because slave_run_triggers_for_rbr=YES makes the replica run its local
      trigger for row events, the trigger's SQLSTATE 45000 error should be
      reported as an apply error. A consistent result would be for the replica SQL
      thread to stop with the trigger error and not silently advance past the row.

      Actual result

      The replica SQL thread remains healthy:

      Slave_IO_Running: Yes
      Slave_SQL_Running: Yes
      Last_SQL_Errno: 0
      Last_SQL_Error:
      

      The row that caused the trigger error under ordinary local execution is present
      on the replica:

      replica.base_t:
        (1, 10, 20, 'fail')
      

      For the variant where the SQLSTATE error is raised before the audit INSERT, the audit
      table remains empty. For the variant where the audit INSERT is executed before
      the SQLSTATE error, the audit row is present and the replica still continues without a
      SQL-thread error.

      Relevant controls

      The same trigger was executed by an ordinary local INSERT on the replica, and
      the local statement failed with error 1644:

      ERROR 1644 (45000): replica side trigger failure
      

      Two trigger bodies were tested:

      -- Variant 1: SIGNAL before the audit INSERT
      SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT='replica side trigger failure';
      INSERT INTO side_audit(row_id,seen_v,seen_g,note)
      VALUES(NEW.id,NEW.v,NEW.g,NEW.note);
       
      -- Variant 2: audit INSERT before SIGNAL
      INSERT INTO side_audit(row_id,seen_v,seen_g,note)
      VALUES(NEW.id,NEW.v,NEW.g,NEW.note);
      SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT='replica side trigger failure';
      

      Both variants show the same error under local execution. Under ROW apply, both
      variants allow the replica SQL thread to remain running after the source row is
      applied.

      Repetition and scope

      The behavior reproduced in the following completed executions:

      MariaDB 12.2.2 -> 12.2.2: 6/6 executions
      MariaDB 10.6   -> 12.2.2: 6/6 executions
      

      Each execution included the local trigger-error control on the replica. The
      replica SQL thread remained running with an empty Last_SQL_Error after ROW
      apply in every execution.

      Nearby issues checked

      This is not a crash-recovery case. The replica is not killed or restarted; the
      replica SQL thread stays running during ordinary ROW apply.

      This is also different from chained trigger logging behavior. There is only one
      replica in this reproduction, and the observation is about propagation of a
      trigger error during local row-event trigger execution.

      Attachments

        Activity

          People

            Deepthi ES Deepthi Eranti Sreenivas
            JaysonL Zhensheng Luo
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Git Integration

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