Skip to content

mariadb-binlog --verify-binlog-checksum --force-read fixes - #5519

Open
ParadoxV5 wants to merge 2870 commits into
MDEV-40647from
MDEV-40542
Open

mariadb-binlog --verify-binlog-checksum --force-read fixes#5519
ParadoxV5 wants to merge 2870 commits into
MDEV-40647from
MDEV-40542

Conversation

@ParadoxV5

@ParadoxV5 ParadoxV5 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

MDEV-40674 Include the checksum for non-corrupted Unknown events

This commit reörders code so the checksum is populated after mariadb-binlog --force generates Unknown_log_event substitutes.
Previously, mariadb-binlog --force inconsistently omitted those checksums from the output even if the checksum is presumably usable.

After merging to 11.4 (MDEV-31273), this commit will also fix «MDEV-40542 MSAN use-of-uninitialized-value on Unknown_log_event::read_checksum_alg», which was exposed by MDEV-31273’s removal of the base Log_event::checksum_alg field.

MDEV-40544 Assertion fail / Memory leak in mariadb-binlog --force-read

(needed this to test MDEV-40674’s checksum failure case)

A checksum error in mariadb-binlog --verify-binlog-checksum --force-read previously resulted in both an error message and an Unknown event substitute, the latter of which failed an assertion in debug builds or became forgotten (memory leak) in non-debug (release) builds.

Since mariadb-binlog --force-read outputs “Unknown event”s rather than errors in other invalid event cases, this commit removes the error status from this situation to match.

raghunandanbhat and others added 30 commits April 20, 2026 23:05
Problem:
  When `$HOME` is set to `~/` (or any string starting with `~/`), the
  `home_dir` is initialized to that value. When `test_if_hard_path` is
  called on a path starting with `~/`, it replaces the `~/` prefix by
  recursively calling `test_if_hard_path(home_dir)` leading to infinite
  recursion and a crash.

Fix:
  Add a check in `test_if_hard_path` to see if `home_dir` itself begins
  with `~/`. If it does, skip the recursive call to prevent the
  infinite loop.
json_get_path_start() set p->last_step to p->steps - 1, creating a
pointer before the beginning of the steps[] array. This is undefined
behavior flagged by UBSAN as "index -1 out of bounds for type
json_path_step_t[32]".

Use NULL as the sentinel value instead, and check for NULL in
json_get_path_next() rather than comparing against p->steps.

Signed-off-by: Varun Deep Saini <varun.23bcs10048@ms.sst.scaler.com>
Signed-off-by: Varun Deep Saini <deepsainivarun@gmail.com>
Similar to ER_LOCK_DEADLOCK and ER_LOCK_WAIT_TIMEOUT, let the ER_CHECKREAD
message suggest that the transaction needs to be restarted. When this error
is reported by InnoDB (only if innodb_snapshot_isolation=ON),
the transaction will be rolled back.

Reviewed by: Sergei Golubchik
Added --galera-info parameter for mysqldump tool and this
will add SET GLOBAL wsrep_start_position line at the
end of the dump. This line is based on added wsrep status
variable wsrep-checkpoint-position.

Added also status variable wsrep-se-checkpoint.
…d Timestamps

Row-based Replication did not validate serialized timestamps,
which allows (pre-11.5) slaves to accept “negative” timestamps
(between the Year 2038 limit and the 4-byte limit) via replication.
In particular, a completely valid source of those timestamps is 11.5.1+
masters, where MDEV-32188 has increased the upper limit of
timestamps to Year 2106 by utilizing this previously invalid range.

This commit fills in this pre-processing:
swap the Year 2106 max with the Year 2038 max,
or throw an “Incorrect timestamp value” error for the others.

Reviewed-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
Update prepare_linux_info() to use /etc/os-release
(PRETTY_NAME) as the primary source for OS detection.

Retain fallback support for /etc/lsb-release and
/etc/*-release for older systems.

Add MTR regression test feedback_os_release.

Signed-off-by: Anway Durge <124391429+itzanway@users.noreply.github.com>
…/NVL2

Item_func_ifnull and Item_func_case_abbreviation2 did not propagate
collation errors when used inside DEFAULT expressions, causing a
diagnostics area assertion instead of returning ER_CANT_AGGREGATE_2COLLATIONS.

Test cases added for IFNULL, IF, and NVL2 in mysql-test/main/create.test.

Reviewed by: Alexander Barkov
Reviewed by: Joro Kodinov
Function calls in INTERVAL expression of DDL have little
sense. SETVAL() fails because sequences require opened tables and
vers_set_interval() is called at earlier stage.

The fix throws ER_SUBQUERIES_NOT_SUPPORTED for sequence functions
SETVAL(), NEXTVAL(), LASTVAL() when the context does not allow
subselect (determined by clause_that_disallows_subselect).
Fix formatting inconsistencies in CONTRIBUTING.md:
- Standardize header underlines to use 3 dashes consistently
- Remove double spaces before links
- Add missing space after period on line 22
- Update http://mariadb.meetup.com/ to https:// for security

These changes improve document readability and follow markdown
best practices.
Until MDEV-32188 on 11.5, both `my_time_t` and the
literal behind the `UINT_MAX32` macro are `signed long`.
But on platforms whose `long` is 32-bit, the value of
`UINT_MAX32` exceeds the range of `signed long`, and so the
macro instead has the next closest data type, `unsigned long`.
Problem:for example SELECT.1 treated as identifier instead of keyword + 0.1
     from starting identifiers after dot
my_realpath() uses my_load_path() as a fallback. my_load_path()
replaces empty string with a current directory. But my_realpath()
didn't do it itself so the result was inconsistent: empty string was
replaced with a current directory, but if the current directory was
symlinked, symlinks were not resolved (as they were for any other,
non-empty, path, including ".").

Fix my_realpath() to treat empty string consisently with all
other paths - replace with a current dir and resolve symlinks too.
The data in MEMORY tables is temporary and is lost when the server
restarts. Thus, it is well-intentioned to record TRUNCATE statements
to the binary log when these tables are rediscovered empty. However,
as entries with no explicit user query associated (especially the lack
of SHUTDOWN on crashes), those unaware of this mechanism can find them
unexpected, not to mention their significance downstream in replication.

This commit adds a comment to these automatically generated
TRUNCATE entries to briefly self-describe their source and purpose.
As a part of the generated query, this comment is visible together
with the TRUNCATE itself in SHOW BINLOG EVENTS and `mariadb-binlog`,
while maintaining seamlessness in replication.

There are no other changes in behaviour or storage engine API.

Reviewed-by: Andrei Elkin <andrei.elkin@mariadb.com>
The data in MEMORY tables is temporary and is lost when the server
restarts. Thus, when these tables are rediscovered empty,
it’s well-intentioned to record TRUNCATE statements to
the binary log, complete with an increment to the `@@gtid_binlog_pos`.
However, those unaware of this mechanism may not expect this increment
and its sign of replication divergence, namely in `@@gtid_strict_mode`.

This commit adds a binary log warning
when such a table is found `implicit_emptied`.

Since general uses of memory tables may already expect this effect,
to avoid unnecessary verbosity, this warning only emits from
`@@read_only` servers with CHANGE MASTER configured. `@@read_only`
indicates that the server should not receive changes; for a slave,
it means it only expects replication to binlog changes with GTID.

Reviewed-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
Fix HeidiSQL download URL

HeidiSQL is now released on github, fix the portable ZIP URL to point
to new download location

HeidiSQL - prevent stale download by providing expected hash
MDEV-29804: Query_log_event::pack_info() was displaying inverted values
for foreign_key_checks, check_constraint_checks and unique_checks flags
in SHOW BINLOG EVENTS.
MDEV-32447: check_constraint_checks was not included in
OPTIONS_WRITTEN_TO_BINLOG, causing replication to break when
check_constraint_checks=OFF was used in non-ROW binlog formats.

Reviewed-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
Reviewed-by: Georgi Kodinov <joro@mariadb.org>
`DBUG_EXECUTE_IF` is a macro that uses
the infamous `do {…} while(0)` “idiom”.
This detail causes the `break` in the code block to terminate the
`while(0)` behind the macro instead of the `for (;;)` outside.
Consequently, this fault simulation does not terminate the normal flow,
which in turn overwrites the simulated fault with a non-fault outcome.

Since this fault simulation is the first step of the loop,
this commit fixes the fault injection by moving it before the loop.
due to argument due to hardcoded mariadb.service.

Fixes: 649216e
…lumns

Problem:
========
A single InnoDB purge worker thread can process undo logs from different
tables within the same batch. But get_purge_table(), open_purge_table()
incorrectly assumes that a 1:1 relationship between a purge worker thread
and a table within a single batch. Based on this wrong assumtion,
InnoDB attempts to reuse TABLE objects cached in thd->open_tables for
virtual column computation.

1) Purge worker opens Table A and caches the TABLE pointer in thd->open_tables.
2) Same purge worker moves to Table B in the same batch, get_purge_table()
retrieves the cached pointer for Table A instead of opening Table B.
3) Because innobase::open() is ignored for Table B, the virtual column
template is never initialized.
4) virtual column computation for Table B aborts the server

Solution:
========
- Introduced purge_table class which has the following
purge_table: Stores either TABLE* (for tables with indexed virtual
columns) or MDL_ticket* (for tables without) in a single union
using LSB as a flag.
For tables with indexed virtual columns: opens TABLE*, accesses
MDL_ticket* via TABLE->mdl_ticket
For tables without indexed virtual columns: stores only MDL_ticket*.

trx_purge_attach_undo_recs(): Coordinator opens both dict_table_t*
and TABLE* with proper MDL protection. Workers access cached
table pointers from purge_node_t->tables without opening
their own handles

purge_sys.coordinator_thd: Distinguish coordinator from workers
in cleanup logic. Skip innobase_reset_background_thd() for
coordinator thread to prevent premature table closure during
batch processing. Workers still call cleanup to release their
thread-local resources

trx_purge_close_tables():
Rewrite for purge coordinator thread
1) Close all dict_table_t* objects first
2) Call close_thread_tables() once for all TABLE* objects
3) Release MDL tickets last, after tables are closed

Added table->lock_mutex protection when reading (or) writing
vc_templ->mysql_table and mysql_table_query_id. Clear cached
TABLE* pointers before closing tables to prevent stale pointer
access

Declared open_purge_table() and close_thread_tables() in trx0purge.cc
Declared reset_thd() in row0purge.cc and dict0stats_bg.cc.
Removed innobase_reset_background_thd()
…lumns

Problem:
========
Purge threads computing virtual columns could crash due to:
1. Stale TABLE* pointers when tables are flushed/rebuilt during purge
2. open_purge_table() called close_thread_tables() on failure, making
MDL tickets invalid before purge could release them
3. Purge coordinator opened TABLE* but workers accessed it with wrong
TABLE->in_use
4. No retry mechanism when open_purge_table() failed due to concurrent
FLUSH TABLES, BACKUP STAGE, or ALTER TABLE operations

Solution:
========
1. Removed close_thread_tables() from open_purge_table(). Purge
coordinator thread should close explicitly in close_and_reopen()

2. Added retry logic: when open_purge_table() returns NULL due to
table flush/rebuild, set must_wait() flag and retry in
close_and_reopen()

3. Update close_and_reopen() with purge_table parameter to
close the failed table. Pass it to trx_purge_close_tables()
for proper cleanup

4. Properly set and reset TABLE::in_use during purge operations:
- Set to coordinator_thd in row_purge_parse_undo_rec() when opening
- Reset in trx_purge_close_table() when closing

5. The auto_increment initialization now happens unconditionally for
purge threads , ensuring the auto_increment counter is always
properly initialized when purge opens tables with virtual columns
originally (MDEV-23570) the idea was to make it TRUE and deprecate.
It cannot be deprecated when it's FALSE, but TRUE breaks
mariabackup.aria_backup where a table is altered from Aria to InnoDB
during a backup, so both t.MAD/t.MAI and t.ibd gets into a backup.
This is MDEV-38866, when it's fixed, keep_files_on_create can be
enabled by default and deprecated at last.
Add support for CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA in COM_CHANGE_USER
packet parsing, allowing passwords >= 251 bytes.

Changes:
- Server: parse_com_change_user_packet() now handles LENENC-encoded
  password length when CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA is set
- Server: fix db pointer calculation for old protocol without
  CLIENT_SECURE_CONNECTION (need +1 to skip null terminator)
- Add regression test for COM_CHANGE_USER with long passwords

Note: This fix requires a corresponding client-side fix in libmariadb's
send_change_user_packet() to send LENENC-encoded passwords.
* update to the fixed libmariadb
* update test to match, remove useless INSTALL PLUGIN
* address remaining review comments
make sure P_S.{global|session}_status and I_S.feedback plugin table
have a column of the same width as I_S.global_status.

Otherwise long status strings (e.g. Ssl_cipher_list) won't fit
and trigger a data truncation warning (an error in the strict mode)
Item_func_quote is not a null-rejecting function
disable main.show_all_plugins if ASAN and RocksDB.

RocksDB has STB_GNU_UNIQUE symbols, so won't be unloaded on dlclose().
Presumably some destructors aren't called, and LSAN doesn't like it.
…rsing

Make sure null terminator byte that is added at the end of header
is within boundaries of 'hdr' array.

This patch is based on #4881
by Uwez Khan
… "-u root" option

rewrite mariadb-backup "early" option parsing to use my_getopt

+ proper handling of values separated from the option by a space (not =)
+ case insensitive and -/_ insensitive comparison
- multiple --defaults-group don't work
- multiple --login-path don't work
- --incremental-dir overwrites --target-dir, not "whatever comes first"
vuvova and others added 21 commits July 29, 2026 13:05
* it's called ROOT_FLAG_VMEM
* it does not imply any protection, ROOT_FLAG_MPROTECT was a misnomer
* it means that the memory is allocated using my_virtual_mem_commit,
  not my_malloc, so not on heap
* memory allocated this way can be protected with my_virtual_mem_protect()
* thus root using ROOT_FLAG_VMEM can be protected with protect_root()

Assisted-By: Claude:claude-5-sonnet
user_var_entry objects and their names have a connection lifetime,
they exist until the connection ends (or is reset), and then they're
all deleted at once. This is exactly the use case for MEM_ROOT,
let's store them there.

Additionally, let's set MY_ROOT_USE_VMEM flag to keep this memroot
off the general heap where user_var_entry values are stored
and where heap buffer overflows can happen.

The latter makes memory allocations for the MEM_ROOT about 10x more
expensive, so let's always start with an empty memroot (= zero overhead
if no user variables are used) and on THD cleanup let's retain one
memroot block (= zero overhead if the next connection takes THD from the
cache and uses user variables up to one block size).

Assisted-By: Claude:claude-4.8-opus
Protect all READ_ONLY sysvars from run-time changes.

Put them into a separate section and use my_virtual_mem_protect()
to make this section read-only before the server starts accepting
connections.

Verify that they're all protected in the sys_var constructor.

One exception: opt_noacl (--skip-grant-tables) can be changed
from 1 to 0 on FLUSH PRIVILEGES. Let's briefly drop the
protection for this 1->0 change. It can be needed only once
in a server lifetime and only if it was started with --skip-grant-tables

On shutdown the protection is removed, making variables writable
again because shutdown resets some of them during the cleanup

Assisted-By: Claude:claude-4.8-opus
Store all READ_ONLY sysvar values in the read_only_root

Even though READ_ONLY sysvars are protected, for string variables
it usually means that the pointer cannot be changed. The value it
points to - the string itself - still can be. Let's store all
values of string READ_ONLY sysvars in the read_only_root.

sysvars that point directly into argv are copied to read_only_root.
sysvars that have their values calculated and allocated now
must be explicitly marked with PREALLOCATED to let it know they
have to be free()-d.

Assisted-By: Claude:claude-4.8-opus
The byteorder field could contain an invalid value (> 1) on a GIS
multi_point object where there byteorder was on any of the inner points.

This can occur with any of the GIS "*FromWKB" functions that contained
a multipoint object.

This result in a invalid object being accepted and also potentially
trigger undefined behaviour in the processing of the object.
Problem was that wsrep_log_state allocated buffer for
String object, but did not set current length. In
wsrep_get_state wsrep transaction state values was
appended to this object but it current length was
same as maximum length allocated leading to fact
that nothing happened.

Fixed by setting String object current length to 0
as it does not yet contain anything and fixed
actual WSREP_DEBUG format.

Removed debug only test case from galera_bf_kill
because same test is on galera_bf_kill_debug test
case. This allows following

(1) galera_bf_kill test case can be run on both
release and debug builds with same result file

(2) galera_bf_kill_debug is run on debug only
because it requires debug sync
When equality propagation (build_equal_items()) merges an equality that
contains a subquery, such as "t1.a = (SELECT ...)", with an outer join's
ON equality, it can inject a reference to that subquery into the ON
expression. If the join columns have compatible types the subquery ends
up as the constant of a multiple equality (which Item::walk() skips); if
they differ (e.g. BIGINT vs INT) the field cannot be merged and the
subquery is substituted in as a plain "tbl.col = (SELECT ...)" argument.

In the latter case, if that outer join is removed by table elimination,
mark_as_eliminated() walks the ON expression and flags the shared
Item_subselect as eliminated. The subquery, however, still lives in
another part of the query and has to be executed, tripping
DBUG_ASSERT(!eliminated) in Item_subselect::exec() (and, in release
builds, disabling the subquery cache and hiding it from EXPLAIN).

The surviving reference can be:
 - a WHERE/HAVING/select-list/ORDER/GROUP expression (subquery written
   there and pushed down into the eliminated ON), or
 - the ON expression of an outer join that was not eliminated (subquery
   written in a surviving outer ON and pushed down into an eliminated
   inner one).

Fix: after table elimination, walk the expressions that survive into
execution (WHERE, HAVING, select list, ORDER/GROUP BY and the ON
expressions of outer joins that were not eliminated) and clear the
"eliminated" flag on any subquery still reachable from them.

Because a subquery can also be the constant of a multiple equality, and
Item::walk() does not visit an Item_equal's constant, Item_equal gets an
unmark_as_eliminated_processor() override that descends into its constant
explicitly.

Assisted by Claude Opus
There's no good reason why undefined behaviour is
acceptable in our codebase let alone having a test that
triggers this.

The thread_stack_basic test because of compulation
has a different stack size under UBSAN. With replace_results
we can include all values of the default stack size
in this test.

plugins.multiauth was added in 031f117 before
CONC-730 and MDEV-31379 corrected the ref10 implementaiton.
Across a range of JSON functions taking a path argument
there are SQL expressions that dont' have a character
set. If these expressions don't have a character set
fall back to the character set of the argument of the
json function that represent the document being operated
on. If this doesn't have a character set fall back to
my_charset_utf8mb4_bin.

This covers the 11.4 JSON_KEY_VALUE function also as it
reuses the Json_path_extractor::extract method.

Add nonnull and warn_unused_result to the json path
functions to facilitate compiler and UBSAN catching of the
problem early.

As null values of s_p are incompatible with report_path_error,
jump directly to a null return which is consistent with
the defination of the JSON sql funciton.
never use item->null_value before this item is evaluated

followup for 14c16e0
valgrind doesn't like it when a process writes to r/o memory
and complains "Bad permissions for mapped region". It's not memcheck,
but valgrind core error, cannot be suppressed.
The "is it my own thread" check compared the login user name
(Security_context::user) and ignored the host, so u1@localhost could see
and kill threads of u1@'127.0.0.1'.

Compare the authenticated account instead:

* all comparisons are done in sctx->is_priv_user() now
* change user_matches() to priv_user_matches(), which uses is_priv_user()
* use it in KILL, KILL USER, SHOW PROCESSLIST, I_S.PROCESSLIST,
  COM_PROCESS_INFO and SHOW EXPLAIN/ANALYZE FOR.
* all the remaining places use is_priv_user() directly instead
  of doing strcmp: SHOW GRANTS, SHOW CREATE PROCEDURE, I_S.VIEWS,
  the DEFINER clause, optimizer trace and change_security_context().

Assisted-by: Claude:claude-5-opus
…risk to crash database

Revert the fix 6ce0682 and implement deduplication differently -
we want an array here to return groups in the order of appearence.
don't convert ulonglong max_mem_used to uint32 before the comparison
Let us remove a number of unused variables to suppress
-Wunused-but-set-global and other warnings.

test_thread(): Instead of incrementing a global counter in a race
condition prone fashion, invoke MY_RELAX_CPU() in order to spend some time.
…EFORE INSERT trigger changes its base column

On the LOAD DATA path the base columns are filled directly from the
input file and fill_record_n_invoke_before_triggers() is then called
with an empty field list (there is no SET clause). After the BEFORE
INSERT trigger changed a base column, the stored generated columns were
not recomputed, so they kept the value derived from the pre-trigger
input (e.g. g=24 instead of 40 for g=v*2 with v set to 20 by the
trigger). A regular INSERT was unaffected.

The recompute was guarded by "fields.elements". That condition is a
leftover from the original computed-columns implementation
(f7a75b9), where fill_record_n_invoke_before_triggers() had no
TABLE* argument and had to reverse-derive the table from the first
item of the field list:

    if (fields.elements)
    {
      fld= (Item_field*)f++;
      item_field= fld->field_for_view_update();
      table= item_field->field->table;
      ...
    }

With an empty field list there was no way to obtain the table, so the
recompute was silently skipped. Since bc4a456 (MDEV-452) the
function receives TABLE* explicitly, which made the whole derivation
dead code (as the in-place DBUG_ASSERT(table == item_field->field->table)
confirmed). Recompute the virtual fields unconditionally on
table->vfield, the same way the Field** overload of
fill_record_n_invoke_before_triggers() already does.
In chain replication (1->2->3), syncing only server_3 after
save_master_gtid on server_1 does not guarantee server_2 has committed,
because server_2's binlog dump thread can send events to server_3 before
commit_ordered() completes on server_2.

Fix affected rpl tests by syncing server_2 before server_3, and update
result files accordingly.

All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the
BSD-new license. I am contributing on behalf of my employer Amazon Web
Services, Inc.
When an uncommitted transaction inserts rows into a table and
another statement locks rows in the same table (SELECT ... FOR UPDATE)
while computing a MIN or MAX, then:
  1. In a Debug build, the server aborts on an assertion
  2. In a Release build, the server returns wrong results
These errors occur because, while reading a group of rows for computing
a MAX, the transaction timeout error was swallowed.

Under the scenario described above and captured in the new test at this
commit, QUICK_GROUP_MIN_MAX_SELECT::next_max() emits a lock timeout error
during QUICK_GROUP_MIN_MAX_SELECT::get_next() but the error was suppressed
if we computed a MIN.

The InnoDB storage engine has an unwritten convention that after it has
returned a fatal error (which is any error except HA_ERR_END_OF_FILE
or HA_ERR_KEY_NOT_FOUND), then the SQL layer should not try to make
any further reads.  This is because InnoDB might have rolled back
the current transaction already.  So in the case of an error, return
immediately from QUICK_GROUP_MIN_MAX_SELECT::get_next().
This commit reörders code so the checksum is populated after
`mariadb-binlog --force` generates `Unknown_log_event` substitutes.
Previously, `mariadb-binlog --force` inconsistently omitted those
checksums from the output even if the checksum is presumably  usable.

After merging to 11.4 (MDEV-31273), this commit will also fix «
MDEV-40542 MSAN use-of-uninitialized-value on Unknown_log_event::read_checksum_alg
», which was exposed by MDEV-31273’s removal
of the base `Log_event::checksum_alg` field.
A checksum error in
`mariadb-binlog --verify-binlog-checksum --force-read` previously
resulted in both an error message and an Unknown event substitute,
the latter of which failed an assertion in debug builds or
became forgotten (memory leak) in non-debug (release) builds.

Since `mariadb-binlog --force-read` outputs “Unknown event”s
rather than errors in other invalid event cases,
this commit removes the error status from this situation to match.
@ParadoxV5
ParadoxV5 requested review from bnestere and knielsen August 9, 2026 22:54
@ParadoxV5 ParadoxV5 added MariaDB Corporation Replication Patches involved in replication labels Aug 9, 2026
@knielsen

knielsen commented Aug 10, 2026 via email

Copy link
Copy Markdown
Member

@ParadoxV5
ParadoxV5 removed the request for review from bnestere August 10, 2026 23:52
@ParadoxV5
ParadoxV5 changed the base branch from 10.11 to MDEV-40647 August 10, 2026 23:53
@ParadoxV5

Copy link
Copy Markdown
Contributor Author

TODO: rebase prior PRs in the stack. nothing to see here~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

MariaDB Corporation Replication Patches involved in replication

Development

Successfully merging this pull request may close these issues.