Skip to content

MDEV-40995 Fix AUTO_INCREMENT race condition in partitioned tables - #5627

Open
greypilgrim-083 wants to merge 1 commit into
MariaDB:10.11from
greypilgrim-083:mdev-40995-fix
Open

MDEV-40995 Fix AUTO_INCREMENT race condition in partitioned tables#5627
greypilgrim-083 wants to merge 1 commit into
MariaDB:10.11from
greypilgrim-083:mdev-40995-fix

Conversation

@greypilgrim-083

@greypilgrim-083 greypilgrim-083 commented Sep 3, 2026

Copy link
Copy Markdown

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_increment rolls the ID pointer backward into an older block. During cleanup, ha_partition::release_auto_increment blindly trusted this pointer because it only checked the .maximum() boundary. This allowed the global counter to be forcefully lowered into already-used territory, resulting in ER_DUP_ENTRY PRIMARY key collisions under concurrent load.

The Fix:
Added a .minimum() boundary check (next_insert_id >= auto_inc_interval_for_cur_row.minimum()) inside ha_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 .test file 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 explicit DEBUG_SYNC points into the C++ source. The fix has been thoroughly validated locally using the reporter's 02_run.sh concurrent stress test.

Please let me know if you would like me to wire up the DEBUG_SYNC sync 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

@CLAassistant

CLAassistant commented Sep 3, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greypilgrim-083

Copy link
Copy Markdown
Author

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)
perfschema.bad_option (server startup option parser test)
binlog_encryption.encrypted_master (encrypted binlog test)
Since my patch strictly modifies auto-increment boundary logic for partitioned tables (ha_partition.cc), it doesn't interact with replication parsing or server startup options. These look like intermittent timing/load issues on the CI runners.

Could a maintainer please re-trigger the failed Buildbot jobs for me when they have a chance?

Thanks!

@gkodinov gkodinov added the External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements. label Sep 4, 2026

@gkodinov gkodinov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@greypilgrim-083
greypilgrim-083 changed the base branch from main to 10.11 September 4, 2026 09:48
@greypilgrim-083

Copy link
Copy Markdown
Author

@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.#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements.

Development

Successfully merging this pull request may close these issues.

3 participants