1
0
mirror of https://github.com/MariaDB/server.git synced 2025-04-18 21:44:20 +03:00
Brandon Nesterenko 79aab08722 MDEV-36290: ALTER TABLE with multi-master can cause data loss
One can have data loss in multi-master setups when 1) both masters
update the same table, 2) ATLER TABLE is run on one master which
re-arranges the column ordering, and 3) transactions are binlogged
in ROW binlog_format. This is because a slave identifies columns to
update using column index number. That is, if a transaction updates
a table with <n> columns on the master, the binary log ROW event
will store its data column-by-column, from the first column, to the
<n>th column, in-order. When the slave applies this row to its
table, it simply updates each column of its new row using these same
values, in the same order. If the slave’s table has its columns in a
different order (from some ALTER TABLE, which can have added,
removed, or re-arranged) these columns, the data will still be
stored in the order that it was done on the master table. This leads
to data loss.

This patch adds the ability for a slave to lookup column name when
applying ROW events, so if the ordering of columns on the master and
slave differs, the slave can still apply the data changes to the
correct column. This is limited to when a master binlogs events
using option binlog_row_metadata=FULL, as this extends
Table_map_log_event metadata to contain column names. When this
column name metadata is missing, the lookup behavior is unchanged
(i.e. it will use column index, as before).

General code changes that extend beyond just this patch:

 1. In unpack_row(), column "cleanup" for fields that don't exist on
    the slave is now done as unpacking is done. Prior to this patch,
    this cleanup would happen only after unpacking the event data, as
    the only place that the event data could have extra rows would be
    after the slave fields had been processed. Now, the slave can be
    missing _any_ field that was logged on the master; and we have to
    account for that as we see it. That is, for fields in the event
    that are missing on the slave, we must move forward the both
    the pointer that tracks the next spot to unpack data, as well as
    account for our null_mask for tracking null columns. To try and
    help ensure this new logic is correct, a new assertion is added,

      assert_master_idx_matches_null_tracking()

    which verifies that our tracking of master indices aligns with
    our null field tracking (albeit this can only be done when all
    fields of a row event are binlogged, e.g when logged with
    binlog_row_image=FULL). Note that we can't meaningfully validate
    our master index is consistent with null bit tracking when we have
    missing columns, as they can be missing in arbitrary places, and if
    we were to track when a bit is written, we would have to refer to
    master_idx, which would invalidate the assertion in the first
    place.

 2. table->{read_set, write_set, rpl_write_set} also needed to be
    updated so its bits would adjust for offset columns on slave. Note
    that rpl_write_set is set in
    TABLE::mark_columns_per_binlog_row_image(), which is pulled from
    10.11. This fixes an existing bug in 10.6 where all slave columns
    wouldn't be written if the slave had additional columns
    (though the bug doesn't exits in 10.11, because it already calls
    mark_columns_per_binlog_row_image()).

 3. There was an issue with the conversion table, where its columns
    weren't in sync with the table_def generated by the
    Table_map_log_event. I.e., when the slave didn't have the column,
    the conv_table generation logic would simply skip the rest of the
    loop and go on to the next column (without adding a field for the
    missing column). The compatible_with and unpack_row logic, however,
    assumed the conv_table was in alignment with the columns from the
    Rows_log_event. I thought of two ways to fix this:
       a. Add a dummy field to the conv_table (and later reset it to
          NULL).
       b. Have a separate index variable which tracks the conv_table
          fields.
    This patch implements the second (b), as it is more efficient.

Patch is currently still being drafted. TODOs left:
 1. Finish MTR testing current changes
 2. Add error-checking logic & MTR tests
 3. Optimize master_to_slave_index_map and master_unmatched_cols
    to use an array and bitmap (per Kristian's review suggestion)
 4. Re-test rpl and multi_source MTR suites with
    binlog_row_metadata=FULL (temporarily change default value) to
    make sure nothing fails from that option alone
 5. Cleanup patch (remove printfs for debugging)
 6. Extensive QA testing

Reviewed By:
============
<TODO>
2025-04-17 17:00:54 -06:00
2023-05-19 14:24:09 +03:00
2024-04-23 14:12:31 +03:00
2025-03-31 12:12:50 +02:00
2025-03-31 12:12:50 +02:00
2023-02-06 20:18:44 +01:00
2025-01-29 11:17:38 +01:00
2022-09-26 13:34:38 +03:00
2025-04-02 04:43:24 +02:00
2025-03-25 09:56:10 +01:00
2025-01-29 11:17:38 +01:00
2024-07-16 15:54:22 +08:00
2025-02-27 04:02:33 +01:00
2025-01-08 08:48:21 +02:00
2025-01-29 11:17:38 +01:00
2025-02-27 04:02:33 +01:00
2025-03-26 17:09:57 +02:00
2024-12-17 11:06:09 +11:00
2025-01-08 08:48:21 +02:00
2024-12-11 14:46:43 +02:00
2024-10-03 09:31:39 +03:00
2025-01-29 11:17:38 +01:00
2022-02-03 17:01:31 +01:00
2024-10-03 09:31:39 +03:00
2024-07-18 16:25:33 +02:00
2024-06-07 10:03:51 +03:00
2024-10-29 14:20:03 +01:00
2024-10-29 14:20:03 +01:00
2021-09-22 07:15:08 +02:00
2019-05-11 21:29:06 +03:00
2024-08-12 09:32:30 +01:00
2024-05-29 13:49:32 +01:00
2025-02-04 10:11:58 -05:00

Code status:

  • Appveyor CI status ci.appveyor.com

MariaDB: The innovative open source database

MariaDB was designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance.

MariaDB is brought to you by the MariaDB Foundation and the MariaDB Corporation. Please read the CREDITS file for details about the MariaDB Foundation, and who is developing MariaDB.

MariaDB is developed by many of the original developers of MySQL who now work for the MariaDB Corporation, the MariaDB Foundation and by many people in the community.

MySQL, which is the base of MariaDB, is a product and trademark of Oracle Corporation, Inc. For a list of developers and other contributors, see the Credits appendix. You can also run 'SHOW authors' to get a list of active contributors.

A description of the MariaDB project and a manual can be found at:

https://mariadb.org

https://mariadb.com/kb/en/

https://mariadb.com/kb/en/mariadb-vs-mysql-features/

https://mariadb.com/kb/en/mariadb-versus-mysql-compatibility/

https://mariadb.com/kb/en/new-and-old-releases/

Getting the code, building it and testing it

Refer to the following guide: https://mariadb.org/get-involved/getting-started-for-developers/get-code-build-test/ which outlines how to build the source code correctly and run the MariaDB testing framework, as well as which branch to target for your contributions.

Help

More help is available from the Maria Discuss mailing list https://lists.mariadb.org/postorius/lists/discuss.lists.mariadb.org/ and MariaDB's Zulip instance, https://mariadb.zulipchat.com/

Licensing


MariaDB is specifically available only under version 2 of the GNU General Public License (GPLv2). (I.e. Without the "any later version" clause.) This is inherited from MySQL. Please see the README file in the MySQL distribution for more information.

License information can be found in the COPYING file. Third party license information can be found in the THIRDPARTY file.


Bug Reports

Bug and/or error reports regarding MariaDB should be submitted at: https://jira.mariadb.org

For reporting security vulnerabilities see: https://mariadb.org/about/security-policy/

The code for MariaDB, including all revision history, can be found at: https://github.com/MariaDB/server

Description
Сервер MariaDB - это разработанный сообществом форк сервера MySQL
https://mariadb.org Readme 2 GiB
Languages
MariaDB\ 71.8%
C++ 16.1%
C 10.6%
Shell 0.5%
Perl 0.4%
Other 0.4%