Skip to content

MDEV-41012 Galera appliers hang with foreign key of types UUID, INET4, INET6 - #5634

Open
sjaakola wants to merge 3 commits into
10.11from
10.11-MDEV-41012
Open

MDEV-41012 Galera appliers hang with foreign key of types UUID, INET4, INET6#5634
sjaakola wants to merge 3 commits into
10.11from
10.11-MDEV-41012

Conversation

@sjaakola

@sjaakola sjaakola commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

wsrep_store_key_val_for_row() built the certification key of a row by collating the column value whenever the field reports MYSQL_TYPE_STRING or MYSQL_TYPE_VAR_STRING, taking the collation from Field::charset().

The data types implemented on Field_fbt - UUID, INET6 and INET4
report MYSQL_TYPE_STRING, and their charset() is my_charset_numeric,
which is latin1. Their values are however plain binary and accordingly
get_innobase_type_from_mysql_type() maps them to DATA_FIXBINARY. Their
keys were therefore run through latin1_swedish_ci, which
folds them. That corrupts the key in two ways:

  1. A key mismatch for one and the same row. The reference key that
    wsrep_rec_get_foreign_key() appends for the parent of a child INSERT is
    built from the InnoDB record and is not collated, so it no longer
    matched the primary key carried by the parent row's own writeset.
    Certification saw no dependency between a child INSERT and a concurrent
    parent UPDATE, and two appliers could apply them in parallel causing
    a hang or crash.

  2. A key collision between distinct rows. The folding is many to one, so
    different values collapse onto one key, Certification compares keys byte
    for byte, so unrelated rows were treated as the same row. Concurrent
    transactions on them certified as a conflict and one was aborted with
    ER_LOCK_DEADLOCK.

Fix is for wsrep_store_key_val_for_row() to skip the collation for
fields that InnoDB stores as binary, using the same condition as
get_innobase_type_from_mysql_type(). This is a no-op for the types that
worked before.

…, INET6

Added a deterministic test for reproducing the issue
…, INET6

Added second test for testing key collisions from transactions modifying
separate rows
…, INET6

wsrep_store_key_val_for_row() built the certification key of a row by
collating the column value whenever the field reports MYSQL_TYPE_STRING
or MYSQL_TYPE_VAR_STRING, taking the collation from Field::charset().

The data types implemented on Field_fbt - UUID, INET6 and INET4
report MYSQL_TYPE_STRING, and their charset() is my_charset_numeric,
which is latin1. Their values are however plain binary and accordingly
get_innobase_type_from_mysql_type() maps them to DATA_FIXBINARY. Their
keys were therefore run through latin1_swedish_ci, which
folds them. That corrupts the key in two ways:

1. A key mismatch for one and the same row. The reference key that
wsrep_rec_get_foreign_key() appends for the parent of a child INSERT is
built from the InnoDB record and is not collated, so it no longer
matched the primary key carried by the parent row's own writeset.
Certification saw no dependency between a child INSERT and a concurrent
parent UPDATE, and two appliers could apply them in parallel causing
a hang or crash.

2. A key collision between distinct rows. The folding is many to one, so
different values collapse onto one key, Certification compares keys byte
 for byte, so unrelated rows were treated as the same row. Concurrent
transactions on them certified as a conflict and one was aborted with
ER_LOCK_DEADLOCK.

Fix is for  wsrep_store_key_val_for_row() to skip the collation for
fields that InnoDB stores as binary, using the same condition as
get_innobase_type_from_mysql_type(). This is a no-op for the types that
worked before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant