MDEV-40995 Fix AUTO_INCREMENT race condition in partitioned tables - #5627
MDEV-40995 Fix AUTO_INCREMENT race condition in partitioned tables#5627greypilgrim-083 wants to merge 1 commit into
Conversation
|
I took a look at the recent CI failures and they appear to be unrelated flaky tests. The specific tests that failed are: main.start_slave_until (replication parser test) Could a maintainer please re-trigger the failed Buildbot jobs for me when they have a chance? Thanks! |
gkodinov
left a comment
There was a problem hiding this comment.
Thank you for your contribution! This is a preliminary review.
Please rebase your fix to 10.11: every bug should be fixed in the lowest affected version.
Also, please make sure there is a commit comment and it is compliant with the contribution guidelines.
235cbf5 to
23d715b
Compare
|
@gkodinov I changed the base branch to 10.11 and added commit message according to contribution guidelines of mariadb |
… can leave the table-level AUTO_INCREMENT counter behind MAX(pk), so later inserts are handed ids that already exist and fail with ER_DUP_ENTRY on the PRIMARY KEY For a partitioned InnoDB table with AUTO_INCREMENT as the leftmost PK column, values are issued by the partitioning layer from the shared counter Partition_share::next_auto_inc_val, reserved in doubling blocks (1, 2, 4, 8 ... values per reservation). At end-of-statement, ha_partition::release_auto_increment() returns unused tail values to the shared counter. When a row fails mid-statement, handler::restore_auto_increment() rolls next_insert_id back to the boundary of an earlier block. The guard in release_auto_increment() inspects only the last interval, so it passes even when the returned value is already in use by concurrent sessions. Fix: extend the guard to also verify that next_insert_id is within the statement's own reservation interval, rejecting a lowering caused by restore_auto_increment() rolling back across a block boundary.#
23d715b to
405c5c2
Compare
Fixes https://jira.mariadb.org/browse/MDEV-40995
The Problem:
When a multi-row insert (or
INSERT ... SELECT) fails on the first row of a newly fetched auto-increment block,restore_auto_incrementrolls the ID pointer backward into an older block. During cleanup,ha_partition::release_auto_incrementblindly trusted this pointer because it only checked the.maximum()boundary. This allowed the global counter to be forcefully lowered into already-used territory, resulting inER_DUP_ENTRYPRIMARY key collisions under concurrent load.The Fix:
Added a
.minimum()boundary check (next_insert_id >= auto_inc_interval_for_cur_row.minimum()) insideha_partition::release_auto_increment. This ensures the global counter is never rolled back below the starting ID of the currently reserved block.Testing Note:
A regression
.testfile is not included because this is a strict multi-threaded race condition. Reliably interleaving the auto-increment block fetches across multiple connections to force the collision would require injecting explicitDEBUG_SYNCpoints into the C++ source. The fix has been thoroughly validated locally using the reporter's02_run.shconcurrent stress test.Please let me know if you would like me to wire up the
DEBUG_SYNCsync points and write the MTR test for this, or if the C++ fix is sufficient as-is!for more detailed analysis of problem please check my comment under https://jira.mariadb.org/browse/MDEV-40995