diff options
author | Vasil Dimov <vasil.dimov@oracle.com> | 2011-02-08 19:28:00 +0200 |
---|---|---|
committer | Vasil Dimov <vasil.dimov@oracle.com> | 2011-02-08 19:28:00 +0200 |
commit | be01dbf5879781eb8969de73cba407eb1f90bff9 (patch) | |
tree | ff814f5d518eaf9c141a355a470b54a53e8ce052 | |
parent | 4e523ad68dce768516f58823667ce0d2484101d0 (diff) | |
parent | 1751fd90a8d16aefcf710299537e160d1e443226 (diff) | |
download | mariadb-git-be01dbf5879781eb8969de73cba407eb1f90bff9.tar.gz |
Merge mysql-5.5-innodb -> mysql-5.5
-rw-r--r-- | mysql-test/valgrind.supp | 42 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.c | 156 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.c | 30 | ||||
-rw-r--r-- | storage/innobase/dict/dict0load.c | 2 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.c | 8 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.c | 8 | ||||
-rw-r--r-- | storage/innobase/include/btr0cur.h | 42 | ||||
-rw-r--r-- | storage/innobase/include/buf0buf.h | 8 | ||||
-rw-r--r-- | storage/innobase/include/row0upd.h | 26 | ||||
-rw-r--r-- | storage/innobase/include/univ.i | 7 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.c | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.c | 14 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.c | 68 | ||||
-rw-r--r-- | storage/innobase/row/row0umod.c | 35 | ||||
-rw-r--r-- | storage/innobase/row/row0upd.c | 43 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.c | 13 | ||||
-rw-r--r-- | storage/innobase/trx/trx0roll.c | 4 |
17 files changed, 321 insertions, 187 deletions
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index bcb01832b6d..e641efbdecc 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -835,3 +835,45 @@ fun:lf_hash_search } +{ + Bug 59874 Valgrind warning in InnoDB compression code + Memcheck:Cond + fun:* + fun:* + fun:deflate + fun:btr_store_big_rec_extern_fields_func + fun:row_ins_index_entry_low + fun:row_ins_index_entry + fun:row_ins_index_entry_step + fun:row_ins + fun:row_ins_step + fun:row_insert_for_mysql +} + +{ + In page0zip.c we have already checked that the memory is initialized before calling deflate() + Memcheck:Cond + fun:* + fun:* + fun:deflate + fun:page_zip_compress +} + +{ + In page0zip.c we have already checked that the memory is initialized before calling deflate() + Memcheck:Cond + fun:* + fun:* + fun:deflate + fun:page_zip_compress_deflate +} + +{ + Bug 59875 Valgrind warning in buf0buddy.c + Memcheck:Addr1 + fun:mach_read_from_4 + fun:buf_buddy_relocate + fun:buf_buddy_free_low + fun:buf_buddy_free + fun:buf_LRU_block_remove_hashed_page +} diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index 8218fc81c13..ff9b1835a53 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -197,7 +197,7 @@ static ulint btr_rec_get_externally_stored_len( /*==============================*/ - rec_t* rec, /*!< in: record */ + const rec_t* rec, /*!< in: record */ const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ #endif /* !UNIV_HOTBACKUP */ @@ -1886,8 +1886,8 @@ btr_cur_update_in_place( NOT call it if index is secondary */ if (!dict_index_is_clust(index) - || row_upd_changes_ord_field_binary(NULL, NULL, - index, update)) { + || row_upd_changes_ord_field_binary(index, update, thr, + NULL, NULL)) { /* Remove possible hash index pointer to this record */ btr_search_update_hash_on_delete(cursor); @@ -3762,34 +3762,62 @@ btr_estimate_number_of_different_key_vals( /*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/ /***********************************************************//** +Gets the offset of the pointer to the externally stored part of a field. +@return offset of the pointer to the externally stored part */ +static +ulint +btr_rec_get_field_ref_offs( +/*=======================*/ + const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + ulint n) /*!< in: index of the external field */ +{ + ulint field_ref_offs; + ulint local_len; + + ut_a(rec_offs_nth_extern(offsets, n)); + field_ref_offs = rec_get_nth_field_offs(offsets, n, &local_len); + ut_a(local_len != UNIV_SQL_NULL); + ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); + + return(field_ref_offs + local_len - BTR_EXTERN_FIELD_REF_SIZE); +} + +/** Gets a pointer to the externally stored part of a field. +@param rec record +@param offsets rec_get_offsets(rec) +@param n index of the externally stored field +@return pointer to the externally stored part */ +#define btr_rec_get_field_ref(rec, offsets, n) \ + ((rec) + btr_rec_get_field_ref_offs(offsets, n)) + +/***********************************************************//** Gets the externally stored size of a record, in units of a database page. @return externally stored part, in units of a database page */ static ulint btr_rec_get_externally_stored_len( /*==============================*/ - rec_t* rec, /*!< in: record */ + const rec_t* rec, /*!< in: record */ const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint n_fields; - byte* data; - ulint local_len; - ulint extern_len; ulint total_extern_len = 0; ulint i; ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec)); + + if (!rec_offs_any_extern(offsets)) { + return(0); + } + n_fields = rec_offs_n_fields(offsets); for (i = 0; i < n_fields; i++) { if (rec_offs_nth_extern(offsets, i)) { - data = rec_get_nth_field(rec, offsets, i, &local_len); - - local_len -= BTR_EXTERN_FIELD_REF_SIZE; - - extern_len = mach_read_from_4(data + local_len - + BTR_EXTERN_LEN + 4); + ulint extern_len = mach_read_from_4( + btr_rec_get_field_ref(rec, offsets, i) + + BTR_EXTERN_LEN + 4); total_extern_len += ut_calc_align(extern_len, UNIV_PAGE_SIZE); @@ -3819,7 +3847,7 @@ btr_cur_set_ownership_of_extern_field( ulint byte_val; data = rec_get_nth_field(rec, offsets, i, &local_len); - + ut_ad(rec_offs_nth_extern(offsets, i)); ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); local_len -= BTR_EXTERN_FIELD_REF_SIZE; @@ -3829,6 +3857,9 @@ btr_cur_set_ownership_of_extern_field( if (val) { byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG); } else { +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG + ut_a(!(byte_val & BTR_EXTERN_OWNER_FLAG)); +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ byte_val = byte_val | BTR_EXTERN_OWNER_FLAG; } @@ -4067,8 +4098,8 @@ file segment of the index tree. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ UNIV_INTERN ulint -btr_store_big_rec_extern_fields( -/*============================*/ +btr_store_big_rec_extern_fields_func( +/*=================================*/ dict_index_t* index, /*!< in: index of rec; the index tree MUST be X-latched */ buf_block_t* rec_block, /*!< in/out: block containing rec */ @@ -4077,11 +4108,17 @@ btr_store_big_rec_extern_fields( the "external storage" flags in offsets will not correspond to rec when this function returns */ - big_rec_t* big_rec_vec, /*!< in: vector containing fields +#ifdef UNIV_DEBUG + mtr_t* local_mtr, /*!< in: mtr containing the + latch to rec and to the tree */ +#endif /* UNIV_DEBUG */ +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG + ibool update_in_place,/*! in: TRUE if the record is updated + in place (not delete+insert) */ +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ + const big_rec_t*big_rec_vec) /*!< in: vector containing fields to be stored externally */ - mtr_t* local_mtr __attribute__((unused))) /*!< in: mtr - containing the latch to rec and to the - tree */ + { ulint rec_page_no; byte* field_ref; @@ -4099,6 +4136,7 @@ btr_store_big_rec_extern_fields( z_stream c_stream; ut_ad(rec_offs_validate(rec, index, offsets)); + ut_ad(rec_offs_any_extern(offsets)); ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); @@ -4130,21 +4168,37 @@ btr_store_big_rec_extern_fields( ut_a(err == Z_OK); } +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG + /* All pointers to externally stored columns in the record + must either be zero or they must be pointers to inherited + columns, owned by this record or an earlier record version. */ + for (i = 0; i < rec_offs_n_fields(offsets); i++) { + if (!rec_offs_nth_extern(offsets, i)) { + continue; + } + field_ref = btr_rec_get_field_ref(rec, offsets, i); + + ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); + /* Either this must be an update in place, + or the BLOB must be inherited, or the BLOB pointer + must be zero (will be written in this function). */ + ut_a(update_in_place + || (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG) + || !memcmp(field_ref, field_ref_zero, + BTR_EXTERN_FIELD_REF_SIZE)); + } +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ /* We have to create a file segment to the tablespace for each field and put the pointer to the field in rec */ for (i = 0; i < big_rec_vec->n_fields; i++) { - ut_ad(rec_offs_nth_extern(offsets, - big_rec_vec->fields[i].field_no)); - { - ulint local_len; - field_ref = rec_get_nth_field( - rec, offsets, big_rec_vec->fields[i].field_no, - &local_len); - ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); - local_len -= BTR_EXTERN_FIELD_REF_SIZE; - field_ref += local_len; - } + field_ref = btr_rec_get_field_ref( + rec, offsets, big_rec_vec->fields[i].field_no); +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG + /* A zero BLOB pointer should have been initially inserted. */ + ut_a(!memcmp(field_ref, field_ref_zero, + BTR_EXTERN_FIELD_REF_SIZE)); +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ extern_len = big_rec_vec->fields[i].len; UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data, extern_len); @@ -4426,6 +4480,23 @@ next_zip_page: mem_heap_free(heap); } +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG + /* All pointers to externally stored columns in the record + must be valid. */ + for (i = 0; i < rec_offs_n_fields(offsets); i++) { + if (!rec_offs_nth_extern(offsets, i)) { + continue; + } + + field_ref = btr_rec_get_field_ref(rec, offsets, i); + + /* The pointer must not be zero. */ + ut_a(0 != memcmp(field_ref, field_ref_zero, + BTR_EXTERN_FIELD_REF_SIZE)); + /* The column must not be disowned by this record. */ + ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); + } +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ return(DB_SUCCESS); } @@ -4448,6 +4519,7 @@ btr_check_blob_fil_page_type( if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) { ulint flags = fil_space_get_flags(space_id); +#ifndef UNIV_DEBUG /* Improve debug test coverage */ if (UNIV_LIKELY ((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) { /* Old versions of InnoDB did not initialize @@ -4456,6 +4528,7 @@ btr_check_blob_fil_page_type( a BLOB page that is in Antelope format.*/ return; } +#endif /* !UNIV_DEBUG */ ut_print_timestamp(stderr); fprintf(stderr, @@ -4505,23 +4578,13 @@ btr_free_externally_stored_field( ulint page_no; ulint next_page_no; mtr_t mtr; -#ifdef UNIV_DEBUG + ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains_page(local_mtr, field_ref, MTR_MEMO_PAGE_X_FIX)); ut_ad(!rec || rec_offs_validate(rec, index, offsets)); - - if (rec) { - ulint local_len; - const byte* f = rec_get_nth_field(rec, offsets, - i, &local_len); - ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); - local_len -= BTR_EXTERN_FIELD_REF_SIZE; - f += local_len; - ut_ad(f == field_ref); - } -#endif /* UNIV_DEBUG */ + ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i)); if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) { @@ -4684,13 +4747,8 @@ btr_rec_free_externally_stored_fields( for (i = 0; i < n_fields; i++) { if (rec_offs_nth_extern(offsets, i)) { - ulint len; - byte* data - = rec_get_nth_field(rec, offsets, i, &len); - ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); - btr_free_externally_stored_field( - index, data + len - BTR_EXTERN_FIELD_REF_SIZE, + index, btr_rec_get_field_ref(rec, offsets, i), rec, offsets, page_zip, i, rb_ctx, mtr); } } diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index e585b15fc21..e825dcd79f9 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -865,9 +865,9 @@ buf_block_init( block->modify_clock = 0; -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG block->page.file_page_was_freed = FALSE; -#endif /* UNIV_DEBUG_FILE_ACCESSES */ +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ block->check_index_page_at_flush = FALSE; block->index = NULL; @@ -2229,7 +2229,7 @@ buf_page_peek_if_search_hashed( return(is_hashed); } -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG /********************************************************************//** Sets file_page_was_freed TRUE if the page is found in the buffer pool. This function should be called when we free a file page and want the @@ -2252,6 +2252,8 @@ buf_page_set_file_page_was_freed( if (bpage) { ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); + /* bpage->file_page_was_freed can already hold + when this code is invoked from dict_drop_index_tree() */ bpage->file_page_was_freed = TRUE; } @@ -2289,7 +2291,7 @@ buf_page_reset_file_page_was_freed( return(bpage); } -#endif /* UNIV_DEBUG_FILE_ACCESSES */ +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ /********************************************************************//** Get read access to a compressed page (usually of type @@ -2390,7 +2392,7 @@ got_block: buf_page_set_accessed_make_young(bpage, access_time); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ut_a(!bpage->file_page_was_freed); #endif @@ -3058,7 +3060,7 @@ wait_until_unfixed: buf_page_set_accessed_make_young(&block->page, access_time); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ut_a(!block->page.file_page_was_freed); #endif @@ -3217,7 +3219,7 @@ buf_page_optimistic_get( ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ut_a(block->page.file_page_was_freed == FALSE); #endif if (UNIV_UNLIKELY(!access_time)) { @@ -3329,7 +3331,7 @@ buf_page_get_known_nowait( ut_a(block->page.buf_fix_count > 0); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ut_a(block->page.file_page_was_freed == FALSE); #endif @@ -3415,9 +3417,9 @@ buf_page_try_get_func( ut_a(block->page.buf_fix_count > 0); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ut_a(block->page.file_page_was_freed == FALSE); -#endif /* UNIV_DEBUG_FILE_ACCESSES */ +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); buf_pool->stat.n_page_gets++; @@ -3446,9 +3448,9 @@ buf_page_init_low( bpage->newest_modification = 0; bpage->oldest_modification = 0; HASH_INVALIDATE(bpage, hash); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG bpage->file_page_was_freed = FALSE; -#endif /* UNIV_DEBUG_FILE_ACCESSES */ +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ } /********************************************************************//** @@ -3807,9 +3809,9 @@ buf_page_create( #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(space, offset) == 0); #endif -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG block->page.file_page_was_freed = FALSE; -#endif /* UNIV_DEBUG_FILE_ACCESSES */ +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ /* Page can be found in buf_pool */ buf_pool_mutex_exit(buf_pool); diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index 3252e85b358..3561e7220ab 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -1552,7 +1552,7 @@ err_len: "InnoDB: in InnoDB data dictionary" " has unknown type %lx.\n", (ulong) flags); - return(NULL); + return("incorrect flags in SYS_TABLES"); } } else { flags = 0; diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c index 5bf5411bc6a..3f09732a676 100644 --- a/storage/innobase/fsp/fsp0fsp.c +++ b/storage/innobase/fsp/fsp0fsp.c @@ -3435,9 +3435,9 @@ fseg_free_page( fseg_free_page_low(seg_inode, space, zip_size, page, mtr); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG buf_page_set_file_page_was_freed(space, page); -#endif +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ } /**********************************************************************//** @@ -3503,13 +3503,13 @@ fseg_free_extent( fsp_free_extent(space, zip_size, page, mtr); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG for (i = 0; i < FSP_EXTENT_SIZE; i++) { buf_page_set_file_page_was_freed(space, first_page_in_extent + i); } -#endif +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ } /**********************************************************************//** diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index e1f61d48a76..93d152bfb74 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -2276,9 +2276,9 @@ ibuf_remove_free_page(void) fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, IBUF_SPACE_ID, page_no, &mtr); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no); -#endif +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ ibuf_enter(); @@ -2322,9 +2322,9 @@ ibuf_remove_free_page(void) ibuf_bitmap_page_set_bits( bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr); -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no); -#endif +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ mtr_commit(&mtr); ibuf_exit(); diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index a9434e2d183..be918439f59 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -500,8 +500,8 @@ file segment of the index tree. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ UNIV_INTERN ulint -btr_store_big_rec_extern_fields( -/*============================*/ +btr_store_big_rec_extern_fields_func( +/*=================================*/ dict_index_t* index, /*!< in: index of rec; the index tree MUST be X-latched */ buf_block_t* rec_block, /*!< in/out: block containing rec */ @@ -510,10 +510,42 @@ btr_store_big_rec_extern_fields( the "external storage" flags in offsets will not correspond to rec when this function returns */ - big_rec_t* big_rec_vec, /*!< in: vector containing fields +#ifdef UNIV_DEBUG + mtr_t* local_mtr, /*!< in: mtr containing the + latch to rec and to the tree */ +#endif /* UNIV_DEBUG */ +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG + ibool update_in_place,/*! in: TRUE if the record is updated + in place (not delete+insert) */ +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ + const big_rec_t*big_rec_vec) /*!< in: vector containing fields to be stored externally */ - mtr_t* local_mtr); /*!< in: mtr containing the latch to - rec and to the tree */ + __attribute__((nonnull)); + +/** Stores the fields in big_rec_vec to the tablespace and puts pointers to +them in rec. The extern flags in rec will have to be set beforehand. +The fields are stored on pages allocated from leaf node +file segment of the index tree. +@param index in: clustered index; MUST be X-latched by mtr +@param b in/out: block containing rec; MUST be X-latched by mtr +@param rec in/out: clustered index record +@param offsets in: rec_get_offsets(rec, index); + the "external storage" flags in offsets will not be adjusted +@param mtr in: mini-transaction that holds x-latch on index and b +@param upd in: TRUE if the record is updated in place (not delete+insert) +@param big in: vector containing fields to be stored externally +@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ +#ifdef UNIV_DEBUG +# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ + btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big) +#elif defined UNIV_BLOB_LIGHT_DEBUG +# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ + btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big) +#else +# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ + btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big) +#endif + /*******************************************************************//** Frees the space in an externally stored field to the file space management if the field in data is owned the externally stored field, diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 7d57cc26288..dbd5adee0cc 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -480,7 +480,7 @@ buf_reset_check_index_page_at_flush( /*================================*/ ulint space, /*!< in: space id */ ulint offset);/*!< in: page number */ -#ifdef UNIV_DEBUG_FILE_ACCESSES +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG /********************************************************************//** Sets file_page_was_freed TRUE if the page is found in the buffer pool. This function should be called when we free a file page and want the @@ -505,7 +505,7 @@ buf_page_reset_file_page_was_freed( /*===============================*/ ulint space, /*!< in: space id */ ulint offset); /*!< in: page number */ -#endif /* UNIV_DEBUG_FILE_ACCESSES */ +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ /********************************************************************//** Reads the freed_page_clock of a buffer block. @return freed_page_clock */ @@ -1403,11 +1403,11 @@ struct buf_page_struct{ 0 if the block was never accessed in the buffer pool */ /* @} */ -# ifdef UNIV_DEBUG_FILE_ACCESSES +# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ibool file_page_was_freed; /*!< this is set to TRUE when fsp frees a page in buffer pool */ -# endif /* UNIV_DEBUG_FILE_ACCESSES */ +# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ }; diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 9c2e003c609..c275c1da78e 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -280,19 +280,29 @@ NOTE: we compare the fields as binary strings! @return TRUE if update vector changes an ordering field in the index record */ UNIV_INTERN ibool -row_upd_changes_ord_field_binary( -/*=============================*/ +row_upd_changes_ord_field_binary_func( +/*==================================*/ + dict_index_t* index, /*!< in: index of the record */ + const upd_t* update, /*!< in: update vector for the row; NOTE: the + field numbers in this MUST be clustered index + positions! */ +#ifdef UNIV_DEBUG + const que_thr_t*thr, /*!< in: query thread */ +#endif /* UNIV_DEBUG */ const dtuple_t* row, /*!< in: old value of row, or NULL if the row and the data values in update are not known when this function is called, e.g., at compile time */ - const row_ext_t*ext, /*!< NULL, or prefixes of the externally + const row_ext_t*ext) /*!< NULL, or prefixes of the externally stored columns in the old row */ - dict_index_t* index, /*!< in: index of the record */ - const upd_t* update) /*!< in: update vector for the row; NOTE: the - field numbers in this MUST be clustered index - positions! */ - __attribute__((nonnull(3,4), warn_unused_result)); + __attribute__((nonnull(1,2), warn_unused_result)); +#ifdef UNIV_DEBUG +# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ + row_upd_changes_ord_field_binary_func(index,update,thr,row,ext) +#else /* UNIV_DEBUG */ +# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ + row_upd_changes_ord_field_binary_func(index,update,row,ext) +#endif /* UNIV_DEBUG */ /***********************************************************//** Checks if an update vector changes an ordering field of an index record. This function is fast if the update vector is short or the number of ordering diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index f8c2d3c1a18..a99b8306eb8 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -184,14 +184,15 @@ command. Not tested on Windows. */ debugging without UNIV_DEBUG */ #define UNIV_BUF_DEBUG /* Enable buffer pool debugging without UNIV_DEBUG */ +#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column + debugging without UNIV_DEBUG */ #define UNIV_DEBUG /* Enable ut_ad() assertions and disable UNIV_INLINE */ #define UNIV_DEBUG_LOCK_VALIDATE /* Enable ut_ad(lock_rec_validate_page()) assertions. */ -#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access - (field file_page_was_freed - in buf_page_t) */ +#define UNIV_DEBUG_FILE_ACCESSES /* Enable freed block access + debugging without UNIV_DEBUG */ #define UNIV_LRU_DEBUG /* debug the buffer pool LRU */ #define UNIV_HASH_DEBUG /* debug HASH_ macros */ #define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */ diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index dbfba358f9f..e0414cde80d 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -2122,7 +2122,7 @@ function_exit: err = btr_store_big_rec_extern_fields( index, btr_cur_get_block(&cursor), - rec, offsets, big_rec, &mtr); + rec, offsets, &mtr, FALSE, big_rec); if (modify) { dtuple_big_rec_free(big_rec); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 63f30276df6..a7b0cabfa4b 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1939,15 +1939,13 @@ err_exit: err = trx->error_state; - if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + switch (err) { + case DB_SUCCESS: + break; + case DB_OUT_OF_FILE_SPACE: trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); - /* TO DO: free table? The code below will dereference - table->name, though. */ - } - switch (err) { - case DB_OUT_OF_FILE_SPACE: ut_print_timestamp(stderr); fputs(" InnoDB: Warning: cannot create table ", stderr); @@ -1962,9 +1960,13 @@ err_exit: break; case DB_DUPLICATE_KEY: + default: /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, NULL); + dict_mem_table_free(table); break; } diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index 08abc8a3e59..83e7c9e4857 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -489,8 +489,11 @@ Purges an update of an existing record. Also purges an update of a delete marked record if that record contained an externally stored field. */ static void -row_purge_upd_exist_or_extern( -/*==========================*/ +row_purge_upd_exist_or_extern_func( +/*===============================*/ +#ifdef UNIV_DEBUG + const que_thr_t*thr, /*!< in: query thread */ +#endif /* UNIV_DEBUG */ purge_node_t* node) /*!< in: row purge node */ { mem_heap_t* heap; @@ -515,8 +518,8 @@ row_purge_upd_exist_or_extern( while (node->index != NULL) { index = node->index; - if (row_upd_changes_ord_field_binary(NULL, NULL, node->index, - node->update)) { + if (row_upd_changes_ord_field_binary(node->index, node->update, + thr, NULL, NULL)) { /* Build the older version of the index entry */ entry = row_build_index_entry(node->row, NULL, index, heap); @@ -598,6 +601,14 @@ skip_secondaries: } } +#ifdef UNIV_DEBUG +# define row_purge_upd_exist_or_extern(thr,node) \ + row_purge_upd_exist_or_extern_func(thr,node) +#else /* UNIV_DEBUG */ +# define row_purge_upd_exist_or_extern(thr,node) \ + row_purge_upd_exist_or_extern_func(node) +#endif /* UNIV_DEBUG */ + /***********************************************************//** Parses the row reference and other info in a modify undo log record. @return TRUE if purge operation required: NOTE that then the CALLER @@ -704,47 +715,32 @@ err_exit: /***********************************************************//** Fetches an undo log record and does the purge for the recorded operation. If none left, or the current purge completed, returns the control to the -parent node, which is always a query thread node. -@return DB_SUCCESS if operation successfully completed, else error code */ -static -ulint +parent node, which is always a query thread node. */ +static __attribute__((nonnull)) +void row_purge( /*======*/ purge_node_t* node, /*!< in: row purge node */ que_thr_t* thr) /*!< in: query thread */ { - roll_ptr_t roll_ptr; - ibool purge_needed; ibool updated_extern; - trx_t* trx; - ut_ad(node && thr); - - trx = thr_get_trx(thr); + ut_ad(node); + ut_ad(thr); - node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr, - &(node->reservation), + node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr, + &node->reservation, node->heap); if (!node->undo_rec) { /* Purge completed for this query thread */ thr->run_node = que_node_get_parent(node); - return(DB_SUCCESS); - } - - node->roll_ptr = roll_ptr; - - if (node->undo_rec == &trx_purge_dummy_rec) { - purge_needed = FALSE; - } else { - purge_needed = row_purge_parse_undo_rec(node, &updated_extern, - thr); - /* If purge_needed == TRUE, we must also remember to unfreeze - data dictionary! */ + return; } - if (purge_needed) { + if (node->undo_rec != &trx_purge_dummy_rec + && row_purge_parse_undo_rec(node, &updated_extern, thr)) { node->found_clust = FALSE; node->index = dict_table_get_next_index( @@ -756,14 +752,14 @@ row_purge( } else if (updated_extern || node->rec_type == TRX_UNDO_UPD_EXIST_REC) { - row_purge_upd_exist_or_extern(node); + row_purge_upd_exist_or_extern(thr, node); } if (node->found_clust) { btr_pcur_close(&(node->pcur)); } - row_mysql_unfreeze_data_dictionary(trx); + row_mysql_unfreeze_data_dictionary(thr_get_trx(thr)); } /* Do some cleanup */ @@ -771,8 +767,6 @@ row_purge( mem_heap_empty(node->heap); thr->run_node = node; - - return(DB_SUCCESS); } /***********************************************************//** @@ -786,9 +780,6 @@ row_purge_step( que_thr_t* thr) /*!< in: query thread */ { purge_node_t* node; -#ifdef UNIV_DEBUG - ulint err; -#endif /* UNIV_DEBUG */ ut_ad(thr); @@ -796,12 +787,7 @@ row_purge_step( ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); -#ifdef UNIV_DEBUG - err = -#endif /* UNIV_DEBUG */ row_purge(node, thr); - ut_ad(err == DB_SUCCESS); - return(thr); } diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index 0d4c42b958c..2188fdeff49 100644 --- a/storage/innobase/row/row0umod.c +++ b/storage/innobase/row/row0umod.c @@ -173,40 +173,26 @@ row_undo_mod_remove_clust_low( mtr_t* mtr, /*!< in: mtr */ ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { - btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; - ibool success; ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); - pcur = &(node->pcur); - btr_cur = btr_pcur_get_btr_cur(pcur); - success = btr_pcur_restore_position(mode, pcur, mtr); + /* Find out if the record has been purged already + or if we can remove it. */ - if (!success) { + if (!btr_pcur_restore_position(mode, &node->pcur, mtr) + || row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { return(DB_SUCCESS); } - /* Find out if we can remove the whole clustered index record */ - - if (node->rec_type == TRX_UNDO_UPD_DEL_REC - && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { - - /* Ok, we can remove */ - } else { - return(DB_SUCCESS); - } + btr_cur = btr_pcur_get_btr_cur(&node->pcur); if (mode == BTR_MODIFY_LEAF) { - success = btr_cur_optimistic_delete(btr_cur, mtr); - - if (success) { - err = DB_SUCCESS; - } else { - err = DB_FAIL; - } + err = btr_cur_optimistic_delete(btr_cur, mtr) + ? DB_SUCCESS + : DB_FAIL; } else { ut_ad(mode == BTR_MODIFY_TREE); @@ -693,8 +679,9 @@ row_undo_mod_upd_exist_sec( while (node->index != NULL) { index = node->index; - if (row_upd_changes_ord_field_binary( - node->row, node->ext, node->index, node->update)) { + if (row_upd_changes_ord_field_binary(node->index, node->update, + thr, + node->row, node->ext)) { /* Build the newest version of the index entry */ entry = row_build_index_entry(node->row, node->ext, diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index b552d879e1c..c6bff0fccd6 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -1192,25 +1192,31 @@ NOTE: we compare the fields as binary strings! @return TRUE if update vector changes an ordering field in the index record */ UNIV_INTERN ibool -row_upd_changes_ord_field_binary( -/*=============================*/ +row_upd_changes_ord_field_binary_func( +/*==================================*/ + dict_index_t* index, /*!< in: index of the record */ + const upd_t* update, /*!< in: update vector for the row; NOTE: the + field numbers in this MUST be clustered index + positions! */ +#ifdef UNIV_DEBUG + const que_thr_t*thr, /*!< in: query thread */ +#endif /* UNIV_DEBUG */ const dtuple_t* row, /*!< in: old value of row, or NULL if the row and the data values in update are not known when this function is called, e.g., at compile time */ - const row_ext_t*ext, /*!< NULL, or prefixes of the externally + const row_ext_t*ext) /*!< NULL, or prefixes of the externally stored columns in the old row */ - dict_index_t* index, /*!< in: index of the record */ - const upd_t* update) /*!< in: update vector for the row; NOTE: the - field numbers in this MUST be clustered index - positions! */ { ulint n_unique; ulint i; const dict_index_t* clust_index; - ut_ad(update); ut_ad(index); + ut_ad(update); + ut_ad(thr); + ut_ad(thr->graph); + ut_ad(thr->graph->trx); n_unique = dict_index_get_n_unique(index); @@ -1263,9 +1269,14 @@ row_upd_changes_ord_field_binary( if (UNIV_LIKELY_NULL(buf)) { if (UNIV_UNLIKELY(buf == field_ref_zero)) { - /* This should never happen, but - we try to fail safe here. */ - ut_ad(0); + /* The externally stored field + was not written yet. This + record should only be seen by + recv_recovery_rollback_active(), + when the server had crashed before + storing the field. */ + ut_ad(thr->graph->trx->is_recovered); + ut_ad(trx_is_recv(thr->graph->trx)); return(TRUE); } @@ -1640,8 +1651,8 @@ row_upd_sec_step( ut_ad(!dict_index_is_clust(node->index)); if (node->state == UPD_NODE_UPDATE_ALL_SEC - || row_upd_changes_ord_field_binary(node->row, node->ext, - node->index, node->update)) { + || row_upd_changes_ord_field_binary(node->index, node->update, + thr, node->row, node->ext)) { return(row_upd_sec_index_entry(node, thr)); } @@ -1971,7 +1982,7 @@ row_upd_clust_rec( index, btr_cur_get_block(btr_cur), rec, rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), - big_rec, mtr); + mtr, TRUE, big_rec); mtr_commit(mtr); } @@ -2169,8 +2180,8 @@ exit_func: row_upd_store_row(node); - if (row_upd_changes_ord_field_binary(node->row, node->ext, index, - node->update)) { + if (row_upd_changes_ord_field_binary(index, node->update, thr, + node->row, node->ext)) { /* Update causes an ordering field (ordering fields within the B-tree) of the clustered index record to change: perform diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index acb448a1a67..2a9ad0e7541 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -1327,13 +1327,16 @@ innobase_start_or_create_for_mysql(void) ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS); - /* TODO: Investigate if SRV_N_PENDING_IOS_PER_THREAD (32) limit - still applies to windows. */ - if (!srv_use_native_aio) { - io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD; - } else { + io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD; + + /* On Windows when using native aio the number of aio requests + that a thread can handle at a given time is limited to 32 + i.e.: SRV_N_PENDING_IOS_PER_THREAD */ +# ifdef __WIN__ + if (srv_use_native_aio) { io_limit = SRV_N_PENDING_IOS_PER_THREAD; } +# endif /* __WIN__ */ os_aio_init(io_limit, srv_n_read_io_threads, diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index 876a00fb935..f9d421e3705 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -47,8 +47,8 @@ Created 3/26/1996 Heikki Tuuri rollback */ #define TRX_ROLL_TRUNC_THRESHOLD 1 -/** In crash recovery, the current trx to be rolled back */ -static trx_t* trx_roll_crash_recv_trx = NULL; +/** In crash recovery, the current trx to be rolled back; NULL otherwise */ +static const trx_t* trx_roll_crash_recv_trx = NULL; /** In crash recovery we set this to the undo n:o of the current trx to be rolled back. Then we can print how many % the rollback has progressed. */ |