diff options
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 5 | ||||
-rw-r--r-- | storage/innobase/include/trx0trx.h | 2 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.cc | 92 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 5 | ||||
-rw-r--r-- | storage/maria/ha_maria.cc | 18 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.c | 25 | ||||
-rw-r--r-- | storage/maria/ma_open.c | 2 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.cc | 14 |
8 files changed, 91 insertions, 72 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index ec1b72244b4..8d19064a658 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1011,9 +1011,10 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, # ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; # endif + bool ahi_enabled= btr_search_enabled && !index()->is_ibuf(); /* We do a dirty read of btr_search_enabled below, and btr_search_guess_on_hash() will have to check it again. */ - if (!btr_search_enabled); + if (!ahi_enabled); else if (btr_search_guess_on_hash(index(), info, tuple, mode, latch_mode, this, mtr)) { @@ -1335,7 +1336,7 @@ release_tree: reached_latched_leaf: #ifdef BTR_CUR_HASH_ADAPT - if (btr_search_enabled && !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)) + if (ahi_enabled && !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)) { if (page_cur_search_with_match_bytes(tuple, mode, &up_match, &up_bytes, diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 0450be89cfb..7d2c3297769 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1109,6 +1109,8 @@ public: ut_ad(!dict_operation); ut_ad(!apply_online_log); ut_ad(!is_not_inheriting_locks()); + ut_ad(check_foreigns); + ut_ad(check_unique_secondary); } /** This has to be invoked on SAVEPOINT or at the end of a statement. diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index e5f8f38ce6c..4c8c5842e13 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -395,6 +395,7 @@ static dberr_t trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) { mtr.commit(); + log_free_check(); mtr.start(); const page_id_t hdr_page_id{rseg->space->id, hdr_addr.page}; @@ -402,61 +403,48 @@ trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) buf_block_t *rseg_hdr= rseg->get(&mtr, &err); if (!rseg_hdr) return err; - if (buf_block_t *block= buf_page_get_gen(hdr_page_id, 0, RW_X_LATCH, - nullptr, BUF_GET_POSSIBLY_FREED, - &mtr, &err)) - { - /* Mark the last undo log totally purged, so that if the system - crashes, the tail of the undo log will not get accessed again. The - list of pages in the undo log tail gets inconsistent during the - freeing of the segment, and therefore purge should not try to - access them again. */ - mtr.write<2,mtr_t::MAYBE_NOP>(*block, block->page.frame + - hdr_addr.boffset + TRX_UNDO_NEEDS_PURGE, 0U); - while (!fseg_free_step_not_header(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + - block->page.frame, &mtr)) - { - rseg_hdr->fix(); - block->fix(); - mtr.commit(); - mtr.start(); - rseg_hdr->page.lock.x_lock(); - block->page.lock.x_lock(); - mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_FIX); - mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY); - } + buf_block_t *block= buf_page_get_gen(hdr_page_id, 0, RW_X_LATCH, + nullptr, BUF_GET_POSSIBLY_FREED, + &mtr, &err); + if (!block) + return err; + + const uint32_t seg_size= + flst_get_len(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->page.frame); + + err= trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset, &mtr); + if (UNIV_UNLIKELY(err != DB_SUCCESS)) + return err; + + ut_ad(rseg->curr_size >= seg_size); + rseg->curr_size-= seg_size; + rseg->history_size--; + + byte *hist= TRX_RSEG + TRX_RSEG_HISTORY_SIZE + rseg_hdr->page.frame; + ut_ad(mach_read_from_4(hist) >= seg_size); + mtr.write<4>(*rseg_hdr, hist, mach_read_from_4(hist) - seg_size); - /* The page list may now be inconsistent, but the length field - stored in the list base node tells us how big it was before we - started the freeing. */ - const uint32_t seg_size= - flst_get_len(TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->page.frame); - - /* We may free the undo log segment header page; it must be freed - within the same mtr as the undo log header is removed from the - history list: otherwise, in case of a database crash, the segment - could become inaccessible garbage in the file space. */ - err= trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset, &mtr); - if (UNIV_UNLIKELY(err != DB_SUCCESS)) - return err; - byte *hist= TRX_RSEG + TRX_RSEG_HISTORY_SIZE + rseg_hdr->page.frame; - if (UNIV_UNLIKELY(mach_read_from_4(hist) < seg_size)) - return DB_CORRUPTION; - mtr.write<4>(*rseg_hdr, hist, mach_read_from_4(hist) - seg_size); - - /* Here we assume that a file segment with just the header page - can be freed in a few steps, so that the buffer pool is not - flooded with bufferfixed pages: see the note in fsp0fsp.cc. */ - while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + - block->page.frame, &mtr)); - - ut_ad(rseg->curr_size >= seg_size); - - rseg->history_size--; - rseg->curr_size -= seg_size; + while (!fseg_free_step_not_header(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + + block->page.frame, &mtr)) + { + block->fix(); + mtr.commit(); + /* NOTE: If the server is killed after the log that was produced + up to this point was written, and before the log from the mtr.commit() + in our caller is written, then the pages belonging to the + undo log will become unaccessible garbage. + + This does not matters when using multiple innodb_undo_tablespaces; + innodb_undo_log_truncate=ON will be able to reclaim the space. */ + log_free_check(); + mtr.start(); + block->page.lock.x_lock(); + mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY); } - return err; + while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + + block->page.frame, &mtr)); + return DB_SUCCESS; } /** Remove unnecessary history data from a rollback segment. diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 4975e72ef0f..837f12a39dd 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -385,9 +385,10 @@ void trx_t::free() dict_operation= false; trx_sys.deregister_trx(this); + check_unique_secondary= true; + check_foreigns= true; assert_freed(); trx_sys.rw_trx_hash.put_pins(this); - mysql_thd= nullptr; // FIXME: We need to avoid this heap free/alloc for each commit. @@ -1373,6 +1374,8 @@ void trx_t::commit_cleanup() state= TRX_STATE_NOT_STARTED; mod_tables.clear(); + check_foreigns= true; + check_unique_secondary= true; assert_freed(); trx_init(this); mutex.wr_unlock(); diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 21d9a00b94e..c245dcea036 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2690,12 +2690,22 @@ int ha_maria::info(uint flag) share->db_record_offset= maria_info.record_offset; if (share->key_parts) { - ulong *to= table->key_info[0].rec_per_key, *end; double *from= maria_info.rec_per_key; - for (end= to+ share->key_parts ; to < end ; to++, from++) - *to= (ulong) (*from + 0.5); + KEY *key, *key_end; + for (key= table->key_info, key_end= key + share->keys; + key < key_end ; key++) + { + ulong *to= key->rec_per_key; + /* Some temporary tables does not allocate rec_per_key */ + if (to) + { + for (ulong *end= to+ key->user_defined_key_parts ; + to < end ; + to++, from++) + *to= (ulong) (*from + 0.5); + } + } } - /* Set data_file_name and index_file_name to point at the symlink value if table is symlinked (Ie; Real name is not same as generated name) diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index baa777edcf0..98ef5c21e55 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -2780,7 +2780,8 @@ static my_bool write_block_record(MARIA_HA *info, const uchar *field_pos; ulong length; if ((record[column->null_pos] & column->null_bit) || - (row->empty_bits[column->empty_pos] & column->empty_bit)) + (column->empty_bit && + (row->empty_bits[column->empty_pos] & column->empty_bit))) continue; field_pos= record + column->offset; @@ -4887,7 +4888,8 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, uchar *field_pos= record + column->offset; /* First check if field is present in record */ if ((record[column->null_pos] & column->null_bit) || - (cur_row->empty_bits[column->empty_pos] & column->empty_bit)) + (column->empty_bit && + (cur_row->empty_bits[column->empty_pos] & column->empty_bit))) { bfill(record + column->offset, column->fill_length, type == FIELD_SKIP_ENDSPACE ? ' ' : 0); @@ -4970,8 +4972,9 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, { uint size_length; if ((record[blob_field->null_pos] & blob_field->null_bit) || - (cur_row->empty_bits[blob_field->empty_pos] & - blob_field->empty_bit)) + (blob_field->empty_bit & + (cur_row->empty_bits[blob_field->empty_pos] & + blob_field->empty_bit))) continue; size_length= blob_field->length - portable_sizeof_char_ptr; blob_lengths+= _ma_calc_blob_length(size_length, length_data); @@ -5825,7 +5828,8 @@ static size_t fill_insert_undo_parts(MARIA_HA *info, const uchar *record, const uchar *column_pos; size_t column_length; if ((record[column->null_pos] & column->null_bit) || - cur_row->empty_bits[column->empty_pos] & column->empty_bit) + (column->empty_bit && + cur_row->empty_bits[column->empty_pos] & column->empty_bit)) continue; column_pos= record+ column->offset; @@ -6006,7 +6010,8 @@ static size_t fill_update_undo_parts(MARIA_HA *info, const uchar *oldrec, */ continue; } - if (old_row->empty_bits[column->empty_pos] & column->empty_bit) + if (column->empty_bit && + (old_row->empty_bits[column->empty_pos] & column->empty_bit)) { if (new_row->empty_bits[column->empty_pos] & column->empty_bit) continue; /* Both are empty; skip */ @@ -6022,8 +6027,9 @@ static size_t fill_update_undo_parts(MARIA_HA *info, const uchar *oldrec, log the original value */ new_column_is_empty= ((newrec[column->null_pos] & column->null_bit) || - (new_row->empty_bits[column->empty_pos] & - column->empty_bit)); + (column->empty_bit && + (new_row->empty_bits[column->empty_pos] & + column->empty_bit))); old_column_pos= oldrec + column->offset; new_column_pos= newrec + column->offset; @@ -7196,7 +7202,8 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, column++, null_field_lengths++) { if ((record[column->null_pos] & column->null_bit) || - row.empty_bits[column->empty_pos] & column->empty_bit) + (column->empty_bit && + row.empty_bits[column->empty_pos] & column->empty_bit)) { if (column->type != FIELD_BLOB) *null_field_lengths= 0; diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 2d9174b4380..7702355b7d1 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -117,7 +117,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, &info.blobs,sizeof(MARIA_BLOB)*share->base.blobs, &info.buff,(share->base.max_key_block_length*2+ share->base.max_key_length), - &info.lastkey_buff,share->base.max_key_length*2+1, + &info.lastkey_buff,share->base.max_key_length*3, &info.first_mbr_key, share->base.max_key_length, &info.maria_rtree_recursion_state, share->have_rtree ? 1024 : 0, diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index a1de9edd997..c0419da7e71 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -2144,9 +2144,17 @@ int ha_myisam::info(uint flag) share->keys_for_keyread.intersect(share->keys_in_use); share->db_record_offset= misam_info.record_offset; if (share->key_parts) - memcpy((char*) table->key_info[0].rec_per_key, - (char*) misam_info.rec_per_key, - sizeof(table->key_info[0].rec_per_key[0])*share->key_parts); + { + ulong *from= misam_info.rec_per_key; + KEY *key, *key_end; + for (key= table->key_info, key_end= key + share->keys; + key < key_end ; key++) + { + memcpy(key->rec_per_key, from, + key->user_defined_key_parts * sizeof(*from)); + from+= key->user_defined_key_parts; + } + } if (table_share->tmp_table == NO_TMP_TABLE) mysql_mutex_unlock(&table_share->LOCK_share); } |