Skip to content

MDEV-38243 Write binlog row events for changes done by cascading FK operations - #5521

Open
sjaakola wants to merge 1 commit into
mainfrom
MDEV-38243-new_API
Open

sjaakola wants to merge 1 commit into
mainfrom
MDEV-38243-new_API

Conversation

@sjaakola

Copy link
Copy Markdown
Contributor

This commit implements a feature which changes the handling of cascading foreign
key operations to write the changes of cascading operations into binlog.
The applying of such transaction, in the slave node, will apply just the binlog
events, and does not execute the actual foreign key cascade operation.
This will simplify the slave side replication applying and make it more predictable
in terms of potential interference with other parallel applying happning
in the node.

This feature can be turned ON/OFF by new variable:
rpl_use_binlog_events_for_fk_cascade, with default value OFF

Since the original version, this PR has changes after two reviews, by Kristian and Serg, mainly to:

  • Supporting slave with old MariaDB version.
    Events logged in cascade operation are additionally flagged with
    the long-standing NO_FOREIGN_KEY_CHECKS_F, so a replica that does
    not understand FK_CASCADE_EVENTS_F still disables foreign key checks
    and does not re-execute the cascade
  • SE/server API now narrows the SE role to just report the changes done by foreign key cascading,
    and server side does most of the work after that.

…perations

1. Overview
This commit implements a feature which changes the handling of cascading foreign
key operations to write the changes of cascading operations into binlog.
The applying of such transaction, in the slave node, will apply just the binlog
events, and does not execute the actual foreign key cascade operation.

Having cascaded FK changes in binlog simplifies the slave side applying and makes
it more predictable in terms of potential interference with other parallel applying
happening in the node.

This feature can be turned ON/OFF by new variable:
rpl_use_binlog_events_for_fk_cascade, with default value OFF

2. Design

The engine reports cascade actions through a new generic service,
include/mysql/service_thd_fk_cascade.h, and carries no binlog knowledge of its
own. It asks whether the server wants to be notified of cascade FK, lets the
server capture the before and after row images at the points where cursor is
positioned, and reports the completed action. The server owns the row
images, the column bitmaps that define them, and every decision about what is
done with them. The engine's only contribution is handler::fk_cascade_fetch_row(),
implemented by ha_innobase, which converts the record the cascade cursor sits on
into MySQL row format.

Server side, the reported rows are queued on the THD in execution order and
written to the binary log at statement end or commit, after the originating
statement's own events; they are discarded on rollback and on rollback to
savepoint. Logging them inline would place every cascade delete ahead of every
deferred update within a statement.

The cascaded FK binlog events have new event flag: FK_CASCADE_EVENTS_F, which
tells the slave applier to skip FK cascading.
Binlog events have also flags to mark both original and derived (cascaded FK) events.
This will make it possible for the slave to autonomously choose whether to use
the derived events in applying or to execute the cascade operation.

Binlogged cascade FK events are also correctly handled in slaves with old MariaDB
version. This is because the events logged in cascade operation are additionally
flagged with the NO_FOREIGN_KEY_CHECKS_F flag, so replica that does not understand
the new FK_CASCADE_EVENTS_F flag, still disables foreign key checks in applying
and does not re-execute the cascade

Conplete design is presented in a design document MDEV-38243-design.md, which can
be removed if PR is merged.

3. Trigger support
The SE/server API delegates the actual work to be done in server side. SE (innodb)
has to call 4 handler functions and prepare row images for the arguments.
With this API, server is notified of cascade FK action to happen, and can react
accordingly.

This commit has implemented the binlogging of cascade FK actions, but
there are two other possible uses as well:
- checking FK constraints after FK child table delete
- calling trigger for the child table delete/update

In the design, these handlers are called consumers.

For supporting triggers, it turned out that BEFORE row type of triggers are
too hard to support. This is because the the handler is called from inside
innodb, having a number of innodb resouces locked and execution residing
inside a innodb mtr. Note that the cascade operation may dive deeper in the
FK constraint chain, and callig BEFORE row trigger would require all this
work to be rolled back to isolate innodb for the trigger call.

AFTER row type of triggers, otoh can be supported  with this API. For these,
the trigger call requests can be queued and called after the statement execution
is complete.

4. Testing

The commit has mtr tests for testing the feature:

  rpl.rpl_fk_cascade_binlog_row                   - feature OFF vs ON
  rpl.rpl_fk_cascade_binlog_row_ordering          - event ordering
  rpl.rpl_fk_cascade_binlog_row_rollback          - discard on rollback
  rpl.rpl_fk_set_null_binlog_row                  - SET NULL capture
  rpl.rpl_fk_cascade_binlog_row_slave_option      - origin OFF / replica ON
  rpl.rpl_fk_cascade_binlog_row_old_slave         - old-replica compatibility
  rpl.rpl_fk_cascade_binlog_row_mixed_eligibility - mixed child eligibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants