Be more liberal in allowing for index merges - #24
Conversation
|
Here's a transcript of my "vibe debugging" session with Claude MySQL Index Merge Sort Union Regression AnalysisProblem StatementA performance regression was identified between MySQL 8.0.34 and 8.4.5 where queries that previously used Example Query: SELECT * FROM myTable WHERE col1 = 1 AND (col2 = 2 OR col3 = 3)In MySQL 8.0.34, this would use index merge optimization. In 8.4.5, it falls back to less efficient single-index strategies. Investigation SummaryKey Findings
Root Cause AnalysisThe regression is caused by changes in MySQL 8.0.34 (Working): // Set inexact flag based on conditions
merge.inexact = (new_tree->merges.size() > 1);
merge.inexact |= !new_tree->keys_map.is_clear_all();MySQL 8.4.5 (Broken): // Replaced logic with assertions that can FAIL
assert(merge.inexact || new_tree->merges.size() == 1);
assert(merge.inexact || new_tree->keys_map.is_clear_all());When These Assertions FailCondition 1:
|
https://perconadev.atlassian.net/browse/PS-11242 percona.clone_consistent_snapshot crashed in a debug build with: [InnoDB] Assertion failure: trx0sys.cc:821: prev_trx == nullptr || prev_trx->id > trx->id #5 trx_sys_validate_trx_list trx0sys.cc:821 #6 trx_erase_lists trx0trx.cc:1838 #8 trx_commit_in_memory trx0trx.cc:2009 ... #21 Clone_persist_gtid::write_to_table clone0repl.cc:475 #24 clone_gtid_thread clone0repl.cc:723 trx_sys->rw_trx_list is required to be ordered by descending trx->id, and trx_sys_validate_trx_list() (UNIV_DEBUG only) enforces it on every erase. The consistent snapshot clone-view feature preallocates a transaction id for a donor read-only transaction (ReadView::clone() in read0read.cc). When that donor is later promoted to read-write via trx_set_rw_mode() -> trx_assign_id_for_rw(), it reuses the preallocated id, which - as the existing comment notes - "might not be received in ascending order" and can therefore be smaller than ids handed out to other transactions in the meantime. trx_assign_id_for_rw() already accounts for this when maintaining the sorted rw_trx_ids vector (the std::upper_bound insert), but trx_add_to_rw_trx_list() always did UT_LIST_ADD_FIRST, which assumes the new id is the greatest. Prepending an out-of-order preallocated id breaks the descending-id ordering of rw_trx_list. The corruption goes unnoticed at insertion time because trx_set_rw_mode() (unlike trx_start_low()) has no post-insert validation, and is only caught later when an unrelated transaction - here the clone GTID persister thread - commits and runs the validation during trx_erase_lists(). Fix trx_add_to_rw_trx_list() to insert a transaction carrying a preallocated_id at the position that preserves descending-id order, mirroring the rw_trx_ids handling. The common case (a freshly allocated id, which is always the greatest) keeps the O(1) prepend, so there is no hot-path regression.
Attempts to address this issue.