diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:13:32 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:13:32 +0100 |
commit | d3935adf7a4ea943583e9e51fe8fa8a2c14521dd (patch) | |
tree | 4125365a32fa25dde9e79ccfb4dcd10269071607 /storage/innobase | |
parent | 85ea99dcaf8fd91fa566a78062dbfa416c2309fe (diff) | |
parent | 14ba37f76f87cc48cae62eb6bdf3cda294dff78d (diff) | |
download | mariadb-git-d3935adf7a4ea943583e9e51fe8fa8a2c14521dd.tar.gz |
mysql-5.5.29 merge
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/fil/fil0fil.c | 71 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 30 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 9 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.c | 14 | ||||
-rw-r--r-- | storage/innobase/include/row0upd.ic | 3 | ||||
-rw-r--r-- | storage/innobase/include/univ.i | 18 | ||||
-rw-r--r-- | storage/innobase/os/os0file.c | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.c | 3 |
8 files changed, 108 insertions, 42 deletions
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 23fe76f2281..8fe33459994 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -187,14 +187,16 @@ struct fil_space_struct { requests on the file */ ibool stop_new_ops; /*!< we set this TRUE when we start - deleting a single-table tablespace */ - ibool is_being_deleted; - /*!< this is set to TRUE when we start - deleting a single-table tablespace and its - file; when this flag is set no further i/o - or flush requests can be placed on this space, - though there may be such requests still being - processed on this space */ + deleting a single-table tablespace. + When this is set following new ops + are not allowed: + * read IO request + * ibuf merge + * file flush + Note that we can still possibly have + new write operations because we don't + check this flag when doing flush + batches. */ ulint purpose;/*!< FIL_TABLESPACE, FIL_LOG, or FIL_ARCH_LOG */ UT_LIST_BASE_NODE_T(fil_node_t) chain; @@ -1286,7 +1288,6 @@ try_again: space->stop_ios = FALSE; space->stop_new_ops = FALSE; - space->is_being_deleted = FALSE; space->purpose = purpose; space->size = 0; space->flags = flags; @@ -2301,11 +2302,9 @@ try_again: return(FALSE); } - ut_a(space); + ut_a(space->stop_new_ops); ut_a(space->n_pending_ops == 0); - space->is_being_deleted = TRUE; - ut_a(UT_LIST_GET_LEN(space->chain) == 1); node = UT_LIST_GET_FIRST(space->chain); @@ -2348,13 +2347,26 @@ try_again: rw_lock_x_lock(&space->latch); #ifndef UNIV_HOTBACKUP - /* Invalidate in the buffer pool all pages belonging to the - tablespace. Since we have set space->is_being_deleted = TRUE, readahead - or ibuf merge can no longer read more pages of this tablespace to the - buffer pool. Thus we can clean the tablespace out of the buffer pool - completely and permanently. The flag is_being_deleted also prevents - fil_flush() from being applied to this tablespace. */ - + /* IMPORTANT: Because we have set space::stop_new_ops there + can't be any new ibuf merges, reads or flushes. We are here + because node::n_pending was zero above. However, it is still + possible to have pending read and write requests: + + A read request can happen because the reader thread has + gone through the ::stop_new_ops check in buf_page_init_for_read() + before the flag was set and has not yet incremented ::n_pending + when we checked it above. + + A write request can be issued any time because we don't check + the ::stop_new_ops flag when queueing a block for write. + + We deal with pending write requests in the following function + where we'd minimally evict all dirty pages belonging to this + space from the flush_list. Not that if a block is IO-fixed + we'll wait for IO to complete. + + To deal with potential read requests by checking the + ::stop_new_ops flag in fil_io() */ buf_LRU_flush_or_remove_pages( id, evict_all ? BUF_REMOVE_ALL_NO_WRITE @@ -2364,6 +2376,15 @@ try_again: mutex_enter(&fil_system->mutex); + /* Double check the sanity of pending ops after reacquiring + the fil_system::mutex. */ + if (fil_space_get_by_id(id)) { + ut_a(space->n_pending_ops == 0); + ut_a(UT_LIST_GET_LEN(space->chain) == 1); + node = UT_LIST_GET_FIRST(space->chain); + ut_a(node->n_pending == 0); + } + success = fil_space_free(id, TRUE); mutex_exit(&fil_system->mutex); @@ -2421,7 +2442,7 @@ fil_tablespace_is_being_deleted( ut_a(space != NULL); - is_being_deleted = space->is_being_deleted; + is_being_deleted = space->stop_new_ops; mutex_exit(&fil_system->mutex); @@ -3695,7 +3716,7 @@ fil_tablespace_deleted_or_being_deleted_in_mem( space = fil_space_get_by_id(id); - if (space == NULL || space->is_being_deleted) { + if (space == NULL || space->stop_new_ops) { mutex_exit(&fil_system->mutex); return(TRUE); @@ -4408,7 +4429,9 @@ fil_io( space = fil_space_get_by_id(space_id); - if (!space) { + /* If we are deleting a tablespace we don't allow any read + operations on that. However, we do allow write operations. */ + if (!space || (type == OS_FILE_READ && space->stop_new_ops)) { mutex_exit(&fil_system->mutex); ut_print_timestamp(stderr); @@ -4624,7 +4647,7 @@ fil_flush( space = fil_space_get_by_id(space_id); - if (!space || space->is_being_deleted) { + if (!space || space->stop_new_ops) { mutex_exit(&fil_system->mutex); return; @@ -4755,7 +4778,7 @@ fil_flush_file_spaces( space; space = UT_LIST_GET_NEXT(unflushed_spaces, space)) { - if (space->purpose == purpose && !space->is_being_deleted) { + if (space->purpose == purpose && !space->stop_new_ops) { space_ids[n_space_ids++] = space->id; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 99606f637fb..0c5cea37cfb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1009,11 +1009,23 @@ convert_error_code_to_mysql( case DB_TABLE_NOT_FOUND: return(HA_ERR_NO_SUCH_TABLE); - case DB_TOO_BIG_RECORD: - my_error(ER_TOO_BIG_ROWSIZE, MYF(0), - page_get_free_space_of_empty(flags - & DICT_TF_COMPACT) / 2); + case DB_TOO_BIG_RECORD: { + /* If prefix is true then a 768-byte prefix is stored + locally for BLOB fields. Refer to dict_table_get_format() */ + bool prefix = ((flags & DICT_TF_FORMAT_MASK) + >> DICT_TF_FORMAT_SHIFT) < UNIV_FORMAT_B; + my_printf_error(ER_TOO_BIG_ROWSIZE, + "Row size too large (> %lu). Changing some columns " + "to TEXT or BLOB %smay help. In current row " + "format, BLOB prefix of %d bytes is stored inline.", + MYF(0), + page_get_free_space_of_empty(flags & + DICT_TF_COMPACT) / 2, + prefix ? "or using ROW_FORMAT=DYNAMIC " + "or ROW_FORMAT=COMPRESSED ": "", + prefix ? DICT_MAX_FIXED_COL_LEN : 0); return(HA_ERR_TO_BIG_ROW); + } case DB_TOO_BIG_INDEX_COL: my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0), @@ -1483,19 +1495,19 @@ innobase_next_autoinc( */ max_value= (~(ulonglong) 0); - /* Current value should never be greater than the maximum. */ - ut_a(current <= max_value); - /* According to MySQL documentation, if the offset is greater than the step then the offset is ignored. */ if (offset > block) { offset = 0; } - /* Check for overflow. */ + /* Check for overflow. Current can be > max_value if the value is + in reality a negative value.The visual studio compilers converts + large double values automatically into unsigned long long datatype + maximum value */ if (block >= max_value || offset > max_value - || current == max_value + || current >= max_value || max_value - offset <= offset) { next_value = max_value; diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 7ef3e954636..a33af4db2fe 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -80,12 +80,13 @@ class ha_innobase: public handler uchar* upd_buf; /*!< buffer used in updates */ ulint upd_buf_size; /*!< the size of upd_buf in bytes */ - uchar srch_key_val1[REC_VERSION_56_MAX_INDEX_COL_LEN + 2]; - uchar srch_key_val2[REC_VERSION_56_MAX_INDEX_COL_LEN + 2]; + uchar srch_key_val1[MAX_KEY_LENGTH + MAX_REF_PARTS*2]; + uchar srch_key_val2[MAX_KEY_LENGTH + MAX_REF_PARTS*2]; /*!< buffers used in converting search key values from MySQL format - to InnoDB format. "+ 2" for the two - bytes where the length is stored */ + to InnoDB format. For each column + 2 bytes are used to store length, + hence MAX_REF_PARTS*2. */ Table_flags int_table_flags; uint primary_key; ulong start_of_scan; /*!< this is set to 1 when we are diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 7b48dcb5280..70af56b99f2 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -2868,6 +2868,14 @@ ibuf_get_volume_buffered_count_func( ut_a(len == 1); ut_ad(trx_sys_multiple_tablespace_format); + if (rec_get_deleted_flag(rec, 0)) { + /* This record has been merged already, + but apparently the system crashed before + the change was discarded from the buffer. + Pretend that the record does not exist. */ + return(0); + } + types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len); switch (UNIV_EXPECT(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, @@ -4176,11 +4184,11 @@ ibuf_delete( page, 1); } #ifdef UNIV_ZIP_DEBUG - ut_a(!page_zip || page_zip_validate(page_zip, page)); + ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ page_cur_delete_rec(&page_cur, index, offsets, mtr); #ifdef UNIV_ZIP_DEBUG - ut_a(!page_zip || page_zip_validate(page_zip, page)); + ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ if (page_zip) { @@ -4295,7 +4303,7 @@ ibuf_delete_rec( an assertion failure after crash recovery. */ btr_cur_set_deleted_flag_for_ibuf( btr_pcur_get_rec(pcur), NULL, TRUE, mtr); - mtr_commit(mtr); + ibuf_mtr_commit(mtr); log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE); DBUG_SUICIDE(); } diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic index 10646241125..6706c9f8c69 100644 --- a/storage/innobase/include/row0upd.ic +++ b/storage/innobase/include/row0upd.ic @@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri # include "trx0trx.h" # include "trx0undo.h" # include "row0row.h" +# include "lock0lock.h" #endif /* !UNIV_HOTBACKUP */ #include "page0zip.h" @@ -171,6 +172,8 @@ row_upd_rec_sys_fields( #if DATA_TRX_ID + 1 != DATA_ROLL_PTR # error "DATA_TRX_ID + 1 != DATA_ROLL_PTR" #endif + ut_ad(lock_check_trx_id_sanity(trx_read_trx_id(rec + offset), + rec, index, offsets, FALSE)); trx_write_trx_id(rec + offset, trx->id); trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr); } diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index ce7181e7bd5..0b0b4b8d04c 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -295,6 +295,24 @@ management to ensure correct alignment for doubles etc. */ ======================== */ +/** There are currently two InnoDB file formats which are used to group +features with similar restrictions and dependencies. Using an enum allows +switch statements to give a compiler warning when a new one is introduced. */ +enum innodb_file_formats_enum { + /** Antelope File Format: InnoDB/MySQL up to 5.1. + This format includes REDUNDANT and COMPACT row formats */ + UNIV_FORMAT_A = 0, + + /** Barracuda File Format: Introduced in InnoDB plugin for 5.1: + This format includes COMPRESSED and DYNAMIC row formats. It + includes the ability to create secondary indexes from data that + is not on the clustered index page and the ability to store more + data off the clustered index page. */ + UNIV_FORMAT_B = 1 +}; + +typedef enum innodb_file_formats_enum innodb_file_formats_t; + /* The 2-logarithm of UNIV_PAGE_SIZE: */ #define UNIV_PAGE_SIZE_SHIFT 14 /* The universal page size of the database */ diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 4857e662121..46eb9c4a935 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -1404,7 +1404,6 @@ os_file_create_func( SetLastError(ERROR_DISK_FULL); return((os_file_t) -1); ); - try_again: ut_a(name); @@ -1526,7 +1525,6 @@ try_again: errno = ENOSPC; return((os_file_t) -1); ); - try_again: ut_a(name); diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 48c36e4b92f..b46b2eacd9d 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -2487,6 +2487,9 @@ row_sel_convert_mysql_key_to_innobase( dfield++; } + DBUG_EXECUTE_IF("innodb_srch_key_buffer_full", + ut_a(buf == (original_buf + buf_len));); + ut_a(buf <= original_buf + buf_len); /* We set the length of tuple to n_fields: we assume that the memory |