summaryrefslogtreecommitdiff
path: root/storage/innobase/dict
Commit message (Collapse)AuthorAgeFilesLines
* Merge 10.7 into 10.8Marko Mäkelä2022-12-071-8/+61
|\
| * Merge 10.6 into 10.7Marko Mäkelä2022-12-071-8/+61
| |\
| | * MDEV-30148 Race condition between non-persistent statistics and purgeMarko Mäkelä2022-12-051-8/+61
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | btr_cur_t::open_random_leaf(): Replaces btr_cur_open_at_rnd_pos(). Acquire a shared latch on each page, and finally release all latches except the one on the leaf page. This fixes a race condition between the purge of history and btr_estimate_number_of_different_key_vals(), which turned out to only hold a buffer-fix on the randomly chosen leaf page. Typically, an assertion would fail in page_rec_is_supremum(). ibuf_contract(): Start from the beginning of the change buffer, to simplify the logic. Starting with commit b42294bc6409794bdbd2051b32fa079d81cea61d it does not matter much where the change buffer merge is being initiated. The race condition may have been introduced as early as mysql/mysql-server@ac74632293bea967b352d1b472abedeeaa921b98 from where it was copied to commit 2e814d4702d71a04388386a9f591d14a35980bfe. Reviewed by: Vladislav Lesin Tested by: Matthias Leich
* | | Merge 10.7 into 10.8Marko Mäkelä2022-11-281-11/+12
|\ \ \ | |/ /
| * | Merge 10.6 into 10.7Marko Mäkelä2022-11-281-11/+12
| |\ \ | | |/
| | * Merge 10.5 into 10.6Marko Mäkelä2022-11-281-11/+12
| | |\
| | | * MDEV-30106 InnoDB fails to validate the change buffer on startupMarko Mäkelä2022-11-281-12/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ibuf_init_at_db_start(): Validate the change buffer root page. A later version may stop creating a change buffer, and this validation check will prevent a downgrade from such later versions. ibuf_max_size_update(): If the change buffer was not loaded, do nothing. dict_boot(): Merge the local variable "error" to "err". Ignore failures of ibuf_init_at_db_start() if innodb_force_recovery>=4.
| | | * Merge 10.4 into 10.5Marko Mäkelä2022-11-092-5/+5
| | | |\
| | | | * Merge 10.3 into 10.4Marko Mäkelä2022-11-092-5/+5
| | | | |\
| | | | | * MDEV-29883 Deadlock between InnoDB statistics update and BLOB insertMarko Mäkelä2022-11-092-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a backport of commit 8b6a308e463f937eb8d2498b04967a222c83af90 from MariaDB Server 10.6.11. No attempt to reproduce the hang in earlier an earlier version of MariaDB Server than 10.6 was made. In each caller of fseg_n_reserved_pages() except ibuf_init_at_db_start() which is a special case for ibuf.index at database startup, we must hold an index latch that prevents concurrent allocation or freeing of index pages. Any operation that allocates or free pages that belong to an index tree must first acquire an index latch in non-shared mode, and while holding that, acquire an index root page latch in non-shared mode. btr_get_size(), btr_get_size_and_reserved(): Assert that a strong enough index latch is being held. dict_stats_update_transient_for_index(), dict_stats_analyze_index(): Acquire a strong enough index latch. These operations had followed the same order of acquiring latches in every InnoDB version since the very beginning (commit c533308a158795f91247e9fe3c7304fa5e7d2b3c). The hang was introduced in commit 2e814d4702d71a04388386a9f591d14a35980bfe which imported mysql/mysql-server@ac74632293bea967b352d1b472abedeeaa921b98 which failed to strengthen the locking requirements of the function btr_get_size().
* | | | | | Merge 10.7 into 10.8Marko Mäkelä2022-11-174-46/+131
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge 10.6 into 10.7Marko Mäkelä2022-11-174-46/+131
| |\ \ \ \ \ | | |/ / / /
| | * | | | MDEV-29603 btr_cur_open_at_index_side() is missing some consistency checksMarko Mäkelä2022-11-174-53/+122
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | btr_cur_t: Zero-initialize all fields in the default constructor. btr_cur_t::index: Remove; it duplicated page_cur.index. Many functions: Remove arguments that were duplicating page_cur_t::index and page_cur_t::block. page_cur_open_level(), btr_pcur_open_level(): Replaces btr_cur_open_at_index_side() for dict_stats_analyze_index(). At the end, release all latches except the dict_index_t::lock and the buf_page_t::lock on the requested page. dict_stats_analyze_index(): Rely on mtr_t::rollback_to_savepoint() to release all uninteresting page latches. btr_search_guess_on_hash(): Simplify the logic, and invoke mtr_t::rollback_to_savepoint(). We will use plain C++ std::vector<mtr_memo_slot_t> for mtr_t::m_memo. In this way, we can avoid setting mtr_memo_slot_t::object to nullptr and instead just remove garbage from m_memo. mtr_t::rollback_to_savepoint(): Shrink the vector. We will be needing this in dict_stats_analyze_index(), where we will release page latches and only retain the index->lock in mtr_t::m_memo. mtr_t::release_last_page(): Release the last acquired page latch. Replaces btr_leaf_page_release(). mtr_t::release(const buf_block_t&): Release a single page latch. Used in btr_pcur_move_backward_from_page(). mtr_t::memo_release(): Replaced with mtr_t::release(). mtr_t::upgrade_buffer_fix(): Acquire a latch for a buffer-fixed page. This replaces the double bookkeeping in btr_cur_t::open_leaf(). Reviewed by: Vladislav Lesin
| | * | | | MDEV-29603: Implement btr_cur_t::open_leaf()Marko Mäkelä2022-11-162-8/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | btr_cur_t::open_leaf(): Replaces btr_cur_open_at_index_side() for most calls, except dict_stats_analyze_index(), which is the only place where we need to open a page at the non-leaf level. Use btr_block_get() for better error handling. Also, use the enumeration type btr_latch_mode wherever possible. Reviewed by: Vladislav Lesin
* | | | | | Merge 10.7 into 10.8Marko Mäkelä2022-11-092-19/+8
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge 10.6 into 10.7Marko Mäkelä2022-11-092-19/+8
| |\ \ \ \ \ | | |/ / / /
| | * | | | MDEV-29504/MDEV-29849 TRUNCATE breaks FOREIGN KEY lockingMarko Mäkelä2022-11-081-17/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ha_innobase::referenced_by_foreign_key(): Protect the check with dict_sys.freeze(), to prevent races with TRUNCATE TABLE. The test innodb.instant_alter_crash has been adjusted for this additional locking. dict_table_is_referenced_by_foreign_key(): Removed (merged to the only caller). create_table_info_t::create_table(): Ignore missing indexes for FOREIGN KEY constraints if foreign_key_checks=0. create_table_info_t::create_table_update_dict(): Rewritten as a static function. Do not return any error. ha_innobase::create(): When trx!=nullptr and we are operating on a persistent table, do not rollback, commit, or release the data dictionary latch. ha_innobase::truncate(): Protect the entire critical section with an exclusive dict_sys.latch, so that ha_innobase::referenced_by_foreign_key() on referenced tables will return a consistent result. In case of a failure, invoke dict_load_foreigns() to restore also any FOREIGN KEY constraints. ha_innobase::free_foreign_key_create_info(): Define inline. lock_release(): Disregard innodb_evict_tables_on_commit_debug=ON when dict_sys.locked() holds. It would hold when fts_load_stopword() is invoked by create_table_info_t::create_table_update_dict(). dict_sys_t::locked(): Return whether the current thread is holding the exclusive dict_sys.latch. dict_sys_t::frozen_not_locked(): Return whether any thread is holding a shared dict_sys.latch. In the test main.mysql_upgrade, the InnoDB persistent statistics will no longer be recalculated in ha_innobase::open() as part of CHECK TABLE ... FOR UPGRADE. They were deleted earlier in the test. Tested by: Matthias Leich
| | * | | | MDEV-29853 Assertion `!strstr(table->name.m_name, "/FTS_") || ↵Thirunarayanan Balathandayuthapani2022-11-081-2/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | purge_sys.must_wait_FTS()' failed in trx_t::commit - Failing debug assertion is to indicate whether the purge thread is waiting when fts auxilary table is being dropped. But assertion fails if the table name contains FTS_. So in fts_drop_table(), InnoDB sets the auxilary table flag in transaction modified table list.
| | * | | | MDEV-29518 ASAN Failure on i_s query when tablespace does rename operationThirunarayanan Balathandayuthapani2022-11-081-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - InnoDB information schema query access the tablespace name after getting freed by concurrent rename operation. To avoid this, InnoDB should take exclusive tablespace latch during rename operation and I_S query should take shared tablespace latch before accessing the name
* | | | | | Merge 10.7 into 10.8Marko Mäkelä2022-11-013-28/+66
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge branch '10.6' into 10.7Oleksandr Byelkin2022-10-293-28/+65
| |\ \ \ \ \ | | |/ / / /
| | * | | | MDEV-29883 Deadlock between InnoDB statistics update and BLOB insertMarko Mäkelä2022-10-262-8/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The test innodb.innodb-wl5522-debug would occasionally hang (especially when run with ./mtr --rr) due to a deadlock between btr_store_big_rec_extern_fields() and dict_stats_analyze_index(). The two threads would acquire the clustered index root page latch and the tablespace latch in the opposite order. The deadlock was possible because dict_stats_analyze_index() was holding the index latch in shared mode and an index root page latch, while waiting for the tablespace latch. If a stronger dict_index_t::lock had been held by dict_stats_analyze_index(), any operations that free or allocate index pages would have been blocked. In each caller of fseg_n_reserved_pages() except ibuf_init_at_db_start() which is a special case for ibuf.index at database startup, we must hold an index latch that prevents concurrent allocation or freeing of index pages. Any operation that allocates or free pages that belong to an index tree must first acquire an index latch in Update or Exclusive mode, and while holding that, acquire an index root page latch in Update or Exclusive mode. dict_index_t::clear(): Also acquire an index latch. Otherwise, the test innodb.insert_into_empty could hang. btr_get_size_and_reserved(): Assert that a strong enough index latch is being held. Only acquire a shared fil_space_t::latch; we are only reading, not modifying any data. dict_stats_update_transient_for_index(), dict_stats_analyze_index(): Acquire a strong enough index latch. Only acquire a shared fil_space_t::latch. These operations had followed the same order of acquiring latches in every InnoDB version since the very beginning (commit c533308a158795f91247e9fe3c7304fa5e7d2b3c). The calls for acquiring tablespace latch had previously been moved in commit 87839258f86196dfca1d3af2a947e570e13eeb94 and commit 1e9c922fa726b22f4522f2a4de0fcb6595404086. The hang was introduced in commit 2e814d4702d71a04388386a9f591d14a35980bfe which imported mysql/mysql-server@ac74632293bea967b352d1b472abedeeaa921b98 which failed to strengthen the locking requirements of the function btr_get_size().
| | * | | | MDEV-28327 InnoDB persistent statistics fail to update after bulk insertThirunarayanan Balathandayuthapani2022-10-252-19/+55
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Background statistics thread should keep the table in the statistics queue itself when the table under bulk insert operation dict_stats_analyze_index(): Set the maximum value for index_stats_t if the table is in bulk operation dict_stats_update(), dict_stats_update_transient_for_index(), dict_stats_update_transient(): Returns DB_SUCCESS_LOCKED_REC if the table under bulk insert operation dict_stats_process_entry_from_recalc_pool(): Add the table back to recalc pool if the table under bulk insert operation
| * | | | | Merge branch 10.6 into 10.7Daniel Black2022-10-251-0/+1
| |\ \ \ \ \ | | |/ / / /
| | * | | | MDEV-24402: InnoDB CHECK TABLE ... EXTENDEDMarko Mäkelä2022-10-211-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Until now, the attribute EXTENDED of CHECK TABLE was ignored by InnoDB, and InnoDB only counted the records in each index according to the current read view. Unless the attribute QUICK was specified, the function btr_validate_index() would be invoked to validate the B-tree structure (the sibling and child links between index pages). The EXTENDED check will not only count all index records according to the current read view, but also ensure that any delete-marked records in the clustered index are waiting for the purge of history, and that all secondary index records point to a version of the clustered index record that is waiting for the purge of history. In other words, no index may contain orphan records. Normal MVCC reads and the non-EXTENDED version of CHECK TABLE would ignore these orphans. Unpurged records merely result in warnings (at most one per index), not errors, and no indexes will be flagged as corrupted due to such garbage. It will remain possible to SELECT data from such indexes or tables (which will skip such records) or to rebuild the table to reclaim some space. We introduce purge_sys.end_view that will be (almost) a copy of purge_sys.view at the end of a batch of purging committed transaction history. It is not an exact copy, because if the size of a purge batch is limited by innodb_purge_batch_size, some records that purge_sys.view would allow to be purged will be left over for subsequent batches. The purge_sys.view is relevant in the purge of committed transaction history, to determine if records are safe to remove. The new purge_sys.end_view is relevant in MVCC operations and in CHECK TABLE ... EXTENDED. It tells which undo log records are safe to access (have not been discarded at the end of a purge batch). purge_sys.clone_oldest_view<true>(): In trx_lists_init_at_db_start(), clone the oldest read view similar to purge_sys_t::clone_end_view() so that CHECK TABLE ... EXTENDED will not report bogus failures between InnoDB restart and the completed purge of committed transaction history. purge_sys_t::is_purgeable(): Replaces purge_sys_t::changes_visible() in the case that purge_sys.latch will not be held by the caller. Among other things, this guards access to BLOBs. It is not safe to dereference any BLOBs of a delete-marked purgeable record, because they may have already been freed. purge_sys_t::view_guard::view(): Return a reference to purge_sys.view that will be protected by purge_sys.latch, held by purge_sys_t::view_guard. purge_sys_t::end_view_guard::view(): Return a reference to purge_sys.end_view while it is protected by purge_sys.end_latch. Whenever a thread needs to retrieve an older version of a clustered index record, it will hold a page latch on the clustered index page and potentially also on a secondary index page that points to the clustered index page. If these pages contain purgeable records that would be accessed by a currently running purge batch, the progress of the purge batch would be blocked by the page latches. Hence, it is safe to make a copy of purge_sys.end_view while holding an index page latch, and consult the copy of the view to determine whether a record should already have been purged. btr_validate_index(): Remove a redundant check. row_check_index_match(): Check if a secondary index record and a version of a clustered index record match each other. row_check_index(): Replaces row_scan_index_for_mysql(). Count the records in each index directly, duplicating the relevant logic from row_search_mvcc(). Initialize check_table_extended_view for CHECK ... EXTENDED while holding an index leaf page latch. If we encounter an orphan record, the copy of purge_sys.end_view that we make is safe for visibility checks, and trx_undo_get_undo_rec() will check for the safety to access each undo log record. Should that check fail, we should return DB_MISSING_HISTORY to report a corrupted index. The EXTENDED check tries to match each secondary index record with every available clustered index record version, by duplicating the logic of row_vers_build_for_consistent_read() and invoking trx_undo_prev_version_build() directly. Before invoking row_check_index_match() on delete-marked clustered index record versions, we will consult purge_sys.is_purgeable() in order to avoid accessing freed BLOBs. We will always check that the DB_TRX_ID or PAGE_MAX_TRX_ID does not exceed the global maximum. Orphan secondary index records will be flagged only if everything up to PAGE_MAX_TRX_ID has been purged. We warn also about clustered index records whose nonzero DB_TRX_ID should have been reset in purge or rollback. trx_set_rw_mode(): Move an assertion from ReadView::set_creator_trx_id(). trx_undo_prev_version_build(): Remove two debug-only parameters, and return an error code instead of a Boolean. trx_undo_get_undo_rec(): Return a pointer to the undo log record, or nullptr if one cannot be retrieved. Instead of consulting the purge_sys.view, consult the purge_sys.end_view to determine which records can be accessed. trx_undo_get_rec_if_purgeable(): A variant of trx_undo_get_undo_rec() that will consult purge_sys.view instead of purge_sys.end_view. TRX_UNDO_CHECK_PURGEABILITY: A new parameter to trx_undo_prev_version_build(), passed by row_vers_old_has_index_entry() so that purge_sys.view instead of purge_sys.end_view will be consulted to determine whether a secondary index record may be safely purged. row_upd_changes_disowned_external(): Remove. This should be more expensive than briefly latching purge_sys in trx_undo_prev_version_build() (which may make use of transactional memory). row_sel_reset_old_vers_heap(): New function, split from row_sel_build_prev_vers_for_mysql(). row_sel_build_prev_vers_for_mysql(): Reorder some parameters to simplify the call to row_sel_reset_old_vers_heap(). row_search_for_mysql(): Replaced with direct calls to row_search_mvcc(). sel_node_get_nth_plan(): Define inline in row0sel.h open_step(): Define at the call site, in simplified form. sel_node_reset_cursor(): Merged with the only caller open_step(). --- ReadViewBase::check_trx_id_sanity(): Remove. Let us handle "future" DB_TRX_ID in a more meaningful way: row_sel_clust_sees(): Return DB_SUCCESS if the record is visible, DB_SUCCESS_LOCKED_REC if it is invisible, and DB_CORRUPTION if the DB_TRX_ID is in the future. row_undo_mod_must_purge(), row_undo_mod_clust(): Silently ignore corrupted DB_TRX_ID. We are in ROLLBACK, and we should have noticed that corruption when we were about to modify the record in the first place (leading us to refuse the operation). row_vers_build_for_consistent_read(): Return DB_CORRUPTION if DB_TRX_ID is in the future. Tested by: Matthias Leich Reviewed by: Vladislav Lesin
* | | | | | Merge 10.7 into 10.8Marko Mäkelä2022-10-132-6/+4
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge 10.6 into 10.7Marko Mäkelä2022-10-132-6/+4
| |\ \ \ \ \ | | |/ / / /
| | * | | | Merge 10.5 into 10.6Marko Mäkelä2022-10-061-2/+2
| | |\ \ \ \ | | | |/ / /
| | | * | | Merge 10.4 into 10.5Marko Mäkelä2022-10-061-2/+2
| | | |\ \ \ | | | | |/ /
| | | | * | Merge 10.3 into 10.4Marko Mäkelä2022-10-051-2/+2
| | | | |\ \ | | | | | |/
| | | | | * MDEV-27927 row_sel_try_search_shortcut_for_mysql() does not latch a page, ↵Vlad Lesin2022-10-051-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | violating read view isolation btr_search_guess_on_hash() would only acquire an index page latch if it is invoked with ahi_latch=NULL. If it's invoked from row_sel_try_search_shortcut_for_mysql() with ahi_latch!=NULL, a page will not be latched, and row_search_mvcc() will get a pointer to the record, which can be changed by some other transaction before the record was stored in result buffer with row_sel_store_mysql_rec() call. ahi_latch argument of btr_cur_search_to_nth_level_func() and btr_pcur_open_with_no_init_func() is used only for row_sel_try_search_shortcut_for_mysql(). btr_cur_search_to_nth_level_func(..., ahi_latch !=0, ...) is invoked only from btr_pcur_open_with_no_init_func(..., ahi_latch !=0, ...), which, in turns, is invoked only from row_sel_try_search_shortcut_for_mysql(). I suppose that separate case with ahi_latch!=0 was intentionally implemented to protect row_sel_store_mysql_rec() call in row_search_mvcc() just after row_sel_try_search_shortcut_for_mysql() call. After the ahi_latch was moved from row_seach_mvcc() to row_sel_try_search_shortcut_for_mysql(), there is no need in it at all if btr_search_guess_on_hash() latches a page unconditionally. And if btr_search_guess_on_hash() latched the page, any access to the record in row_sel_try_search_shortcut_for_mysql() after btr_pcur_open_with_no_init() call will be protected with the page latch. The fix is to remove ahi_latch argument from btr_pcur_open_with_no_init_func(), btr_cur_search_to_nth_level_func() and btr_search_guess_on_hash(). There will not be test, as to test it we need to freeze some SELECT execution in the point between row_sel_try_search_shortcut_for_mysql() and row_sel_store_mysql_rec() calls in row_search_mvcc(), and to change the record in some other transaction to let row_sel_store_mysql_rec() to store changed record in result buffer. Buf we can't do this with the fix, as the page will be latched in btr_search_guess_on_hash() call.
| | * | | | MDEV-29440 fixup: Clean up dict_load_foreigns()Marko Mäkelä2022-10-051-4/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dict_load_foreigns(): Remove the constant parameter uncommitted=false. The parameter only had to be added to dict_load_foreign(). Spotted by Alexey Midenkov
* | | | | | Merge branch '10.7' into 10.8Oleksandr Byelkin2022-10-041-1/+1
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge branch '10.6' into 10.7Oleksandr Byelkin2022-10-041-1/+1
| |\ \ \ \ \ | | |/ / / /
| | * | | | Merge branch '10.5' into 10.6Sergei Golubchik2022-09-301-1/+1
| | |\ \ \ \ | | | |/ / /
* | | | | | Merge 10.7 into 10.8Nayuta Yanagisawa2022-09-091-123/+179
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge 10.6 into 10.7Nayuta Yanagisawa2022-09-081-123/+179
| |\ \ \ \ \ | | |/ / / /
| | * | | | MDEV-29440 InnoDB instant ALTER TABLE recovery must use READ UNCOMMITTEDMarko Mäkelä2022-09-081-123/+179
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In commit 8f8ba758559e473f643baa0a0601d321c42517b9 (MDEV-27234) the data dictionary recovery was changed to use READ COMMITTED so that table-rebuild operations (OPTIMIZE TABLE, TRUNCATE TABLE, some forms of ALTER TABLE) would be recovered correctly. However, for operations that avoid a table rebuild thanks to being able to instantly ADD, DROP or reorder columns, recovery must use the READ UNCOMMITTED isolation level so that changes to the hidden metadata record can be rolled back. We will detect instant operations by detecting uncommitted changes to SYS_COLUMNS in case there is no uncommitted change of SYS_TABLES.ID for the table. In any table-rebuilding DDL operation, the SYS_TABLES.ID (and likely also the table name) will be updated. As part of rolling back the instant ALTER TABLE operation, after the operation on the hidden metadata record has been rolled back, a rollback of an INSERT into SYS_COLUMNS in row_undo_ins_remove_clust_rec() will invoke trx_t::evict_table() to discard the READ UNCOMMITTED definition of the table. After that, subsequent recovery steps will load and use the correct table definition. Reviewed by: Thirunarayanan Balathandayuthapani Tested by: Matthias Leich
* | | | | | Merge 10.7 into 10.8Jan Lindström2022-09-051-1/+0
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge 10.6 into 10.7Jan Lindström2022-09-051-1/+0
| |\ \ \ \ \ | | |/ / / /
| | * | | | Merge 10.5 into 10.6Jan Lindström2022-09-051-1/+0
| | |\ \ \ \ | | | |/ / /
| | | * | | Merge 10.4 into 10.5Jan Lindström2022-09-051-1/+0
| | | |\ \ \ | | | | |/ /
| | | | * | Reduce compilation dependencies on wsrep_mysqld.hDaniele Sciascia2022-08-311-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Making changes to wsrep_mysqld.h causes large parts of server code to be recompiled. The reason is that wsrep_mysqld.h is included by sql_class.h, even tough very little of wsrep_mysqld.h is needed in sql_class.h. This commit introduces a new header file, wsrep_on.h, which is meant to be included from sql_class.h, and contains only macros and variable declarations used to determine whether wsrep is enabled. Also, header wsrep.h should only contain definitions that are also used outside of sql/. Therefore, move WSREP_TO_ISOLATION* and WSREP_SYNC_WAIT macros to wsrep_mysqld.h. Reviewed-by: Jan Lindström <jan.lindstrom@mariadb.com>
* | | | | | Merge 10.7 into 10.8Marko Mäkelä2022-08-303-6/+9
|\ \ \ \ \ \ | |/ / / / /
| * | | | | Merge 10.6 into 10.7Marko Mäkelä2022-08-303-6/+9
| |\ \ \ \ \ | | |/ / / /
| | * | | | Merge 10.5 into 10.6Marko Mäkelä2022-08-301-4/+6
| | |\ \ \ \ | | | |/ / /
| | | * | | Merge 10.4 into 10.5Marko Mäkelä2022-08-301-4/+6
| | | |\ \ \ | | | | |/ /
| | | | * | Merge 10.3 into 10.4Marko Mäkelä2022-08-301-4/+6
| | | | |\ \ | | | | | |/
| | | | | * MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLEMarko Mäkelä2022-08-301-4/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dict_table_rename_in_cache(), dict_table_get_highest_foreign_id(): Reserve sufficient space for the fkid[] buffer, and ensure that the fkid[] will be NUL-terminated. The fkid[] must accommodate both the database name (which is already encoded in my_charset_filename) and the constraint name (which must be converted to my_charset_filename) so that we can check if it is in the format databasename/tablename_ibfk_1 (all encoded in my_charset_filename).
| | * | | | Merge 10.5 into 10.6Marko Mäkelä2022-08-251-1/+1
| | |\ \ \ \ | | | |/ / /