diff --git a/sql-bench/myisam.cnf b/sql-bench/myisam.cnf old mode 100644 new mode 100755 diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index 488212f087c..1349ac9e474 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -1349,27 +1349,13 @@ btr_cur_optimistic_insert( Subtract one byte for the encoded heap_no in the modification log. */ ulint free_space_zip = page_zip_empty_size( - cursor->index->n_fields, zip_size) - 1; + cursor->index->n_fields, zip_size); ulint n_uniq = dict_index_get_n_unique_in_tree(index); ut_ad(dict_table_is_comp(index->table)); - /* There should be enough room for two node pointer - records on an empty non-leaf page. This prevents - infinite page splits. */ - - if (UNIV_LIKELY(entry->n_fields >= n_uniq) - && UNIV_UNLIKELY(REC_NODE_PTR_SIZE - + rec_get_converted_size_comp_prefix( - index, entry->fields, n_uniq, - NULL) - /* On a compressed page, there is - a two-byte entry in the dense - page directory for every record. - But there is no record header. */ - - (REC_N_NEW_EXTRA_BYTES - 2) - > free_space_zip / 2)) { - + if (free_space_zip == 0) { +too_big: if (big_rec_vec) { dtuple_convert_back_big_rec( index, entry, big_rec_vec); @@ -1377,6 +1363,27 @@ btr_cur_optimistic_insert( return(DB_TOO_BIG_RECORD); } + + /* Subtract one byte for the encoded heap_no in the + modification log. */ + free_space_zip--; + + /* There should be enough room for two node pointer + records on an empty non-leaf page. This prevents + infinite page splits. */ + + if (entry->n_fields >= n_uniq + && (REC_NODE_PTR_SIZE + + rec_get_converted_size_comp_prefix( + index, entry->fields, n_uniq, NULL) + /* On a compressed page, there is + a two-byte entry in the dense + page directory for every record. + But there is no record header. */ + - (REC_N_NEW_EXTRA_BYTES - 2) + > free_space_zip / 2)) { + goto too_big; + } } LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index ae4b2fba98d..1084dcdf344 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -581,6 +581,8 @@ UNIV_INTERN ibool buf_page_is_corrupted( /*==================*/ + ibool check_lsn, /*!< in: TRUE if we need to check + and complain about the LSN */ const byte* read_buf, /*!< in: a database page */ ulint zip_size) /*!< in: size of compressed page; 0 for uncompressed pages */ @@ -600,7 +602,7 @@ buf_page_is_corrupted( } #ifndef UNIV_HOTBACKUP - if (recv_lsn_checks_on) { + if (check_lsn && recv_lsn_checks_on) { ib_uint64_t current_lsn; if (log_peek_lsn(¤t_lsn) @@ -1998,7 +2000,7 @@ lookup: buf_read_page(space, zip_size, offset, trx); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 37 || buf_validate()); + ut_a(++buf_dbg_counter % 5771 || buf_validate()); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ } @@ -2556,6 +2558,10 @@ loop2: retries = 0; } else if (retries < BUF_PAGE_READ_MAX_RETRIES) { ++retries; + DBUG_EXECUTE_IF( + "innodb_page_corruption_retries", + retries = BUF_PAGE_READ_MAX_RETRIES; + ); } else { fprintf(stderr, "InnoDB: Error: Unable" " to read tablespace %lu page no" @@ -2577,7 +2583,7 @@ loop2: } #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 37 || buf_validate()); + ut_a(++buf_dbg_counter % 5771 || buf_validate()); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ goto loop; } @@ -2593,6 +2599,7 @@ got_block: /* The page is being read to buffer pool, but we cannot wait around for the read to complete. */ +null_exit: //buf_pool_mutex_exit(buf_pool); mutex_exit(block_mutex); @@ -2603,7 +2610,6 @@ got_block: srv_pass_corrupt_table <= 1)) { mutex_exit(block_mutex); - return(NULL); } @@ -2622,6 +2628,14 @@ got_block: case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_DIRTY: ut_ad(block_mutex == &buf_pool->zip_mutex); + if (mode == BUF_PEEK_IF_IN_POOL) { + /* This mode is only used for dropping an + adaptive hash index. There cannot be an + adaptive hash index for a compressed-only + page, so do not bother decompressing the page. */ + goto null_exit; + } + bpage = &block->page; /* Protect bpage->buf_fix_count. */ //mutex_enter(&buf_pool->zip_mutex); @@ -3779,7 +3793,7 @@ buf_page_create( memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - ut_a(++buf_dbg_counter % 357 || buf_validate()); + ut_a(++buf_dbg_counter % 5771 || buf_validate()); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(buf_block_get_space(block), @@ -3933,7 +3947,7 @@ buf_page_io_complete( /* From version 3.23.38 up we store the page checksum to the 4 first bytes of the page end lsn field */ - if (buf_page_is_corrupted(frame, + if (buf_page_is_corrupted(TRUE, frame, buf_page_get_zip_size(bpage))) { corrupt: fprintf(stderr, diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c index 5edbeadb64e..628107d64dc 100644 --- a/storage/xtradb/buf/buf0rea.c +++ b/storage/xtradb/buf/buf0rea.c @@ -220,7 +220,7 @@ not_to_recover: ut_ad(buf_page_in_file(bpage)); - if(sync) { + if (sync) { thd_wait_begin(NULL, THD_WAIT_DISKIO); } diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c index 90e5e7eb7f6..70798b09fec 100644 --- a/storage/xtradb/dict/dict0crea.c +++ b/storage/xtradb/dict/dict0crea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -42,6 +42,22 @@ Created 1/8/1996 Heikki Tuuri #include "trx0roll.h" #include "usr0sess.h" #include "ut0vec.h" +#include "ha_prototypes.h" + +/************************************************************************* +Checks if a table name contains the string TEMP_TABLE_PATH_PREFIX which +denotes temporary tables in MySQL. */ +static +ibool +row_is_mysql_tmp_table_name( +/*========================*/ + /* out: TRUE if temporary table */ + const char* name) /* in: table name in the form + 'database/tablename' */ +{ + return(strstr(name, TEMP_TABLE_PATH_PREFIX) != NULL); +} + /*****************************************************************//** Based on a table object, this function builds the entry to be inserted @@ -1630,18 +1646,46 @@ dict_create_add_foreign_to_dictionary( { ulint error; ulint i; - - pars_info_t* info = pars_info_create(); + pars_info_t* info; if (foreign->id == NULL) { /* Generate a new constraint id */ ulint namelen = strlen(table->name); char* id = mem_heap_alloc(foreign->heap, namelen + 20); - /* no overflow if number < 1e13 */ - sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++); + + if (row_is_mysql_tmp_table_name(table->name)) { + sprintf(id, "%s_ibfk_%lu", table->name, + (ulong) (*id_nr)++); + } else { + char table_name[MAX_TABLE_NAME_LEN + 20] = ""; + uint errors = 0; + + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN + 20); + + innobase_convert_to_system_charset( + strchr(table_name, '/') + 1, + strchr(table->name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN + 20); + } + + sprintf(id, "%s_ibfk_%lu", table_name, + (ulong) (*id_nr)++); + + if (innobase_check_identifier_length( + strchr(id,'/') + 1)) { + return(DB_IDENTIFIER_TOO_LONG); + } + } foreign->id = id; } + info = pars_info_create(); + pars_info_add_str_literal(info, "id", foreign->id); pars_info_add_str_literal(info, "for_name", table->name); diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 817da6e6074..619634028af 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -775,8 +775,11 @@ dict_table_get( /* If table->ibd_file_missing == TRUE, this will print an error message and return without doing anything. */ - dict_update_statistics(table, TRUE /* only update stats - if they have not been initialized */, FALSE); + dict_update_statistics( + table, + TRUE, /* only update stats if not initialized */ + FALSE, + FALSE /* update even if not changed too much */); } return(table); @@ -1119,22 +1122,78 @@ dict_table_rename_in_cache( dict_mem_foreign_table_name_lookup_set(foreign, FALSE); } if (strchr(foreign->id, '/')) { + /* This is a >= 4.0.18 format id */ + ulint db_len; char* old_id; + char old_name_cs_filename[MAX_TABLE_NAME_LEN+20]; + uint errors = 0; - /* This is a >= 4.0.18 format id */ + /* All table names are internally stored in charset + my_charset_filename (except the temp tables and the + partition identifier suffix in partition tables). The + foreign key constraint names are internally stored + in UTF-8 charset. The variable fkid here is used + to store foreign key constraint name in charset + my_charset_filename for comparison further below. */ + char fkid[MAX_TABLE_NAME_LEN+20]; + ibool on_tmp = FALSE; + + /* The old table name in my_charset_filename is stored + in old_name_cs_filename */ + + strncpy(old_name_cs_filename, old_name, + MAX_TABLE_NAME_LEN); + if (strstr(old_name, TEMP_TABLE_PATH_PREFIX) == NULL) { + + innobase_convert_to_system_charset( + strchr(old_name_cs_filename, '/') + 1, + strchr(old_name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + /* There has been an error to convert + old table into UTF-8. This probably + means that the old table name is + actually in UTF-8. */ + innobase_convert_to_filename_charset( + strchr(old_name_cs_filename, + '/') + 1, + strchr(old_name, '/') + 1, + MAX_TABLE_NAME_LEN); + } else { + /* Old name already in + my_charset_filename */ + strncpy(old_name_cs_filename, old_name, + MAX_TABLE_NAME_LEN); + } + } + + strncpy(fkid, foreign->id, MAX_TABLE_NAME_LEN); + + if (strstr(fkid, TEMP_TABLE_PATH_PREFIX) == NULL) { + innobase_convert_to_filename_charset( + strchr(fkid, '/') + 1, + strchr(foreign->id, '/') + 1, + MAX_TABLE_NAME_LEN+20); + } else { + on_tmp = TRUE; + } old_id = mem_strdup(foreign->id); - if (ut_strlen(foreign->id) > ut_strlen(old_name) + if (ut_strlen(fkid) > ut_strlen(old_name_cs_filename) + ((sizeof dict_ibfk) - 1) - && !memcmp(foreign->id, old_name, - ut_strlen(old_name)) - && !memcmp(foreign->id + ut_strlen(old_name), + && !memcmp(fkid, old_name_cs_filename, + ut_strlen(old_name_cs_filename)) + && !memcmp(fkid + ut_strlen(old_name_cs_filename), dict_ibfk, (sizeof dict_ibfk) - 1)) { /* This is a generated >= 4.0.18 format id */ + char table_name[MAX_TABLE_NAME_LEN] = ""; + uint errors = 0; + if (strlen(table->name) > strlen(old_name)) { foreign->id = mem_heap_alloc( foreign->heap, @@ -1142,11 +1201,36 @@ dict_table_rename_in_cache( + strlen(old_id) + 1); } + /* Convert the table name to UTF-8 */ + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN); + innobase_convert_to_system_charset( + strchr(table_name, '/') + 1, + strchr(table->name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + /* Table name could not be converted + from charset my_charset_filename to + UTF-8. This means that the table name + is already in UTF-8 (#mysql#50). */ + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN); + } + /* Replace the prefix 'databasename/tablename' with the new names */ - strcpy(foreign->id, table->name); - strcat(foreign->id, - old_id + ut_strlen(old_name)); + strcpy(foreign->id, table_name); + if (on_tmp) { + strcat(foreign->id, + old_id + ut_strlen(old_name)); + } else { + sprintf(strchr(foreign->id, '/') + 1, + "%s%s", + strchr(table_name, '/') +1, + strstr(old_id, "_ibfk_") ); + } + } else { /* This is a >= 4.0.18 format id where the user gave the id name */ @@ -1529,6 +1613,10 @@ dict_index_too_big_for_tree( /* maximum allowed size of a node pointer record */ ulint page_ptr_max; + DBUG_EXECUTE_IF( + "ib_force_create_table", + return(FALSE);); + comp = dict_table_is_comp(table); zip_size = dict_table_zip_size(table); @@ -1543,7 +1631,10 @@ dict_index_too_big_for_tree( number in the page modification log. The maximum allowed node pointer size is half that. */ page_rec_max = page_zip_empty_size(new_index->n_fields, - zip_size) - 1; + zip_size); + if (page_rec_max) { + page_rec_max--; + } page_ptr_max = page_rec_max / 2; /* On a compressed page, there is a two-byte entry in the dense page directory for every record. But there @@ -4707,7 +4798,12 @@ dict_update_statistics( update/recalc the stats if they have not been initialized yet, otherwise do nothing */ - ibool sync) /*!< in: TRUE if must update SYS_STATS */ + ibool sync, /*!< in: TRUE if must update + SYS_STATS */ + ibool only_calc_if_changed_too_much)/*!< in: only + update/recalc the stats if the table + has been changed too much since the + last stats update/recalc */ { dict_index_t* index; ulint sum_of_index_sizes = 0; @@ -4758,7 +4854,10 @@ dict_update_statistics( dict_table_stats_lock(table, RW_X_LATCH); - if (only_calc_if_missing_stats && table->stat_initialized) { + if ((only_calc_if_missing_stats && table->stat_initialized) + || (only_calc_if_changed_too_much + && !DICT_TABLE_CHANGED_TOO_MUCH(table))) { + dict_table_stats_unlock(table, RW_X_LATCH); return; } @@ -5000,8 +5099,14 @@ dict_table_print_low( ut_ad(mutex_own(&(dict_sys->mutex))); - if (srv_stats_auto_update) - dict_update_statistics(table, FALSE /* update even if initialized */, FALSE); + if (srv_stats_auto_update) { + + dict_update_statistics( + table, + FALSE /* update even if initialized */, + FALSE, + FALSE /* update even if not changed too much */); + } dict_table_stats_lock(table, RW_S_LATCH); diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c index cdef0d1b270..1bc3a204221 100644 --- a/storage/xtradb/dict/dict0load.c +++ b/storage/xtradb/dict/dict0load.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Innobase Oy. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -354,8 +354,11 @@ dict_process_sys_tables_rec( /* Update statistics if DICT_TABLE_UPDATE_STATS is set */ - dict_update_statistics(*table, FALSE /* update even if - initialized */, FALSE); + dict_update_statistics( + *table, + FALSE, /* update even if initialized */ + FALSE, + FALSE /* update even if not changed too much */); } return(NULL); diff --git a/storage/xtradb/dyn/dyn0dyn.c b/storage/xtradb/dyn/dyn0dyn.c index e1275f040f3..d0f50ad0c32 100644 --- a/storage/xtradb/dyn/dyn0dyn.c +++ b/storage/xtradb/dyn/dyn0dyn.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -35,7 +35,7 @@ UNIV_INTERN dyn_block_t* dyn_array_add_block( /*================*/ - dyn_array_t* arr) /*!< in: dyn array */ + dyn_array_t* arr) /*!< in/out: dyn array */ { mem_heap_t* heap; dyn_block_t* block; diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c index ff4e5b1b033..929e24d20ce 100644 --- a/storage/xtradb/fil/fil0fil.c +++ b/storage/xtradb/fil/fil0fil.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -681,7 +681,7 @@ fil_node_open_file( fil_system_t* system, /*!< in: tablespace memory cache */ fil_space_t* space) /*!< in: space */ { - ib_uint64_t size_bytes; + ib_int64_t size_bytes; ulint size_low; ulint size_high; ibool ret; @@ -723,8 +723,8 @@ fil_node_open_file( os_file_get_size(node->handle, &size_low, &size_high); - size_bytes = (((ib_uint64_t)size_high) << 32) - + (ib_uint64_t)size_low; + size_bytes = (((ib_int64_t)size_high) << 32) + + (ib_int64_t)size_low; #ifdef UNIV_HOTBACKUP if (trx_sys_sys_space(space->id)) { node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); @@ -735,7 +735,7 @@ fil_node_open_file( ut_a(space->purpose != FIL_LOG); ut_a(!trx_sys_sys_space(space->id)); - if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { + if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Error: the size of single-table" " tablespace file %s\n" @@ -1883,11 +1883,63 @@ fil_write_flushed_lsn_to_data_files( return(DB_SUCCESS); } +/*******************************************************************//** +Checks the consistency of the first data page of a data file +at database startup. +@retval NULL on success, or if innodb_force_recovery is set +@return pointer to an error message string */ +static __attribute__((warn_unused_result)) +const char* +fil_check_first_page( +/*=================*/ + const page_t* page, /*!< in: data page */ + ibool first_page) /*!< in: TRUE if this is the + first page of the tablespace */ +{ + ulint space_id; + ulint flags; + + if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) { + return(NULL); + } + + space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page); + flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + + if (first_page && !space_id && !flags) { + ulint nonzero_bytes = UNIV_PAGE_SIZE; + const byte* b = page; + + while (!*b && --nonzero_bytes) { + b++; + } + + if (!nonzero_bytes) { + return("space header page consists of zero bytes"); + } + } + + if (buf_page_is_corrupted( + FALSE, page, dict_table_flags_to_zip_size(flags))) { + return("checksum mismatch"); + } + + if (!first_page + || (page_get_space_id(page) == space_id + && page_get_page_no(page) == 0)) { + return(NULL); + } + + return("inconsistent data in space header"); +} + /*******************************************************************//** Reads the flushed lsn, arch no, and tablespace flag fields from a data -file at database startup. */ +file at database startup. +@retval NULL on success, or if innodb_force_recovery is set +@return pointer to an error message string */ UNIV_INTERN -void +const char* fil_read_first_page( /*================*/ os_file_t data_file, /*!< in: open data file */ @@ -1909,6 +1961,7 @@ fil_read_first_page( byte* buf; page_t* page; ib_uint64_t flushed_lsn; + const char* check_msg; buf = ut_malloc(2 * UNIV_PAGE_SIZE); /* Align the memory for a possible read from a raw device */ @@ -1916,13 +1969,18 @@ fil_read_first_page( os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE); - *flags = mach_read_from_4(page + - FSP_HEADER_OFFSET + FSP_SPACE_FLAGS); + *flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN); + check_msg = fil_check_first_page(page, !one_read_already); + ut_free(buf); + if (check_msg) { + return(check_msg); + } + if (!one_read_already) { *min_flushed_lsn = flushed_lsn; *max_flushed_lsn = flushed_lsn; @@ -1930,7 +1988,7 @@ fil_read_first_page( *min_arch_log_no = arch_log_no; *max_arch_log_no = arch_log_no; #endif /* UNIV_LOG_ARCHIVE */ - return; + return(NULL); } if (*min_flushed_lsn > flushed_lsn) { @@ -1947,6 +2005,8 @@ fil_read_first_page( *max_arch_log_no = arch_log_no; } #endif /* UNIV_LOG_ARCHIVE */ + + return(NULL); } /*================ SINGLE-TABLE TABLESPACES ==========================*/ @@ -3271,6 +3331,7 @@ fil_open_single_table_tablespace( os_file_t file; char* filepath; ibool success; + const char* check_msg; byte* buf2; byte* page; ulint space_id; @@ -3331,6 +3392,8 @@ fil_open_single_table_tablespace( success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE); + check_msg = fil_check_first_page(page, TRUE); + /* We have to read the tablespace id and flags from the file. */ space_id = fsp_header_get_space_id(page); @@ -3366,7 +3429,7 @@ fil_open_single_table_tablespace( current_lsn = log_get_lsn(); /* check the header page's consistency */ - if (buf_page_is_corrupted(page, + if (buf_page_is_corrupted(TRUE, page, dict_table_flags_to_zip_size(space_flags))) { fprintf(stderr, "InnoDB: page 0 of %s seems corrupt.\n", filepath); file_is_corrupt = TRUE; @@ -3788,8 +3851,20 @@ skip_write: ut_free(buf2); - if (UNIV_UNLIKELY(space_id != id - || space_flags != (flags & ~(~0 << DICT_TF_BITS)))) { + if (check_msg) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error: %s in file ", check_msg); + ut_print_filename(stderr, filepath); + fprintf(stderr, " (tablespace id=%lu, flags=%lu)\n" + "InnoDB: Please refer to " REFMAN + "innodb-troubleshooting-datadict.html\n", + (ulong) id, (ulong) flags); + success = FALSE; + goto func_exit; + } + + if (space_id != id + || space_flags != (flags & ~(~0 << DICT_TF_BITS))) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: tablespace id and flags in file ", @@ -4136,7 +4211,7 @@ fil_load_single_table_tablespace( ulint flags; ulint size_low; ulint size_high; - ib_uint64_t size; + ib_int64_t size; #ifdef UNIV_HOTBACKUP fil_space_t* space; #endif @@ -4257,9 +4332,9 @@ fil_load_single_table_tablespace( /* Every .ibd file is created >= 4 pages in size. Smaller files cannot be ok. */ - size = (((ib_uint64_t)size_high) << 32) + (ib_uint64_t)size_low; + size = (((ib_int64_t)size_high) << 32) + (ib_int64_t)size_low; #ifndef UNIV_HOTBACKUP - if (size < (ib_uint64_t)FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { + if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Error: the size of single-table tablespace" " file %s\n" @@ -4279,11 +4354,22 @@ fil_load_single_table_tablespace( /* Align the memory for file i/o if we might have O_DIRECT set */ page = ut_align(buf2, UNIV_PAGE_SIZE); - if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { + if (size >= FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) { + const char* check_msg; + success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE); /* We have to read the tablespace id from the file */ + check_msg = fil_check_first_page(page, TRUE); + + if (check_msg) { + fprintf(stderr, + "InnoDB: Error: %s in file %s", + check_msg, filepath); + goto func_exit; + } + space_id = fsp_header_get_space_id(page); flags = fsp_header_get_flags(page); } else { @@ -4863,12 +4949,14 @@ fil_extend_space_to_desired_size( #ifdef HAVE_POSIX_FALLOCATE if (srv_use_posix_fallocate) { - offset_high = size_after_extend * page_size / (4ULL*1024*1024*1024); - offset_low = size_after_extend * page_size % (4ULL*1024*1024*1024); + offset_high = (size_after_extend - file_start_page_no) + * page_size / (4ULL * 1024 * 1024 * 1024); + offset_low = (size_after_extend - file_start_page_no) + * page_size % (4ULL * 1024 * 1024 * 1024); mutex_exit(&fil_system->mutex); success = os_file_set_size(node->name, node->handle, - offset_low, offset_high); + offset_low, offset_high); mutex_enter(&fil_system->mutex); if (success) { node->size += (size_after_extend - start_page_no); @@ -4935,12 +5023,12 @@ fil_extend_space_to_desired_size( mem_free(buf2); + fil_node_complete_io(node, fil_system, OS_FILE_WRITE); + #ifdef HAVE_POSIX_FALLOCATE complete_io: #endif - fil_node_complete_io(node, fil_system, OS_FILE_WRITE); - *actual_size = space->size; #ifndef UNIV_HOTBACKUP diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c index d5717638f29..772e224f6f7 100644 --- a/storage/xtradb/fsp/fsp0fsp.c +++ b/storage/xtradb/fsp/fsp0fsp.c @@ -2910,15 +2910,15 @@ fsp_reserve_free_pages( ulint space, /*!< in: space id, must be != 0 */ fsp_header_t* space_header, /*!< in: header of that space, x-latched */ - ulint size, /*!< in: size of the tablespace in pages, - must be < FSP_EXTENT_SIZE / 2 */ + ulint size, /*!< in: size of the tablespace in + pages, must be < FSP_EXTENT_SIZE */ mtr_t* mtr) /*!< in: mtr */ { xdes_t* descr; ulint n_used; ut_a(space != 0); - ut_a(size < FSP_EXTENT_SIZE / 2); + ut_a(size < FSP_EXTENT_SIZE); descr = xdes_get_descriptor_with_space_hdr(space_header, space, 0, mtr); @@ -3001,7 +3001,7 @@ fsp_reserve_free_extents( try_again: size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr); - if (size < FSP_EXTENT_SIZE / 2) { + if (size < FSP_EXTENT_SIZE) { /* Use different rules for small single-table tablespaces */ *n_reserved = 0; return(fsp_reserve_free_pages(space, space_header, size, mtr)); @@ -3016,11 +3016,8 @@ try_again: some of them will contain extent descriptor pages, and therefore will not be free extents */ - if (size <= free_limit) { - n_free_up = 0; - } else { - n_free_up = (size - free_limit) / FSP_EXTENT_SIZE; - } + ut_ad(size >= free_limit); + n_free_up = (size - free_limit) / FSP_EXTENT_SIZE; if (n_free_up > 0) { n_free_up--; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 3c2e9714f37..48c639c6abc 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -124,7 +124,6 @@ static mysql_cond_t commit_cond; static mysql_mutex_t commit_cond_m; static bool innodb_inited = 0; - #define INSIDE_HA_INNOBASE_CC /* In the Windows plugin, the return value of current_thd is @@ -206,7 +205,6 @@ static uint innobase_buffer_pool_shm_key = 0; static ulint srv_lazy_drop_table = 0; - static char* internal_innobase_data_file_path = NULL; static char* innodb_version_str = (char*) INNODB_VERSION_STR; @@ -874,6 +872,10 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_rows_read, SHOW_LONG}, {"rows_updated", (char*) &export_vars.innodb_rows_updated, SHOW_LONG}, + {"read_views_memory", + (char*) &export_vars.innodb_read_views_memory, SHOW_LONG}, + {"descriptors_memory", + (char*) &export_vars.innodb_descriptors_memory, SHOW_LONG}, {"s_lock_os_waits", (char*) &export_vars.innodb_s_lock_os_waits, SHOW_LONGLONG}, {"s_lock_spin_rounds", @@ -1300,6 +1302,8 @@ convert_error_code_to_mysql( return(HA_ERR_UNDO_REC_TOO_BIG); case DB_OUT_OF_MEMORY: return(HA_ERR_OUT_OF_MEM); + case DB_IDENTIFIER_TOO_LONG: + return(HA_ERR_INTERNAL_ERROR); } } @@ -1380,6 +1384,31 @@ innobase_convert_from_table_id( strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors); } +/********************************************************************** +Check if the length of the identifier exceeds the maximum allowed. +return true when length of identifier is too long. */ +extern "C" +my_bool +innobase_check_identifier_length( +/*=============================*/ + const char* id) /* in: FK identifier to check excluding the + database portion. */ +{ + int well_formed_error = 0; + CHARSET_INFO *cs = system_charset_info; + DBUG_ENTER("innobase_check_identifier_length"); + + uint res = cs->cset->well_formed_len(cs, id, id + strlen(id), + NAME_CHAR_LEN, + &well_formed_error); + + if (well_formed_error || res == NAME_CHAR_LEN) { + my_error(ER_TOO_LONG_IDENT, MYF(0), id); + DBUG_RETURN(true); + } + DBUG_RETURN(false); +} + /******************************************************************//** Converts an identifier to UTF-8. */ extern "C" UNIV_INTERN @@ -3076,25 +3105,29 @@ innobase_change_buffering_inited_ok: /* Force doublewrite buffer off, atomic writes replace it. */ if (srv_use_doublewrite_buf) { - fprintf(stderr, "InnoDB: Switching off doublewrite buffer " + fprintf(stderr, + "InnoDB: Switching off doublewrite buffer " "because of atomic writes.\n"); - innobase_use_doublewrite = srv_use_doublewrite_buf = FALSE; + innobase_use_doublewrite = FALSE; + srv_use_doublewrite_buf = FALSE; } - /* Force O_DIRECT on Unixes (on Windows writes are always unbuffered)*/ + /* Force O_DIRECT on Unixes (on Windows writes are always + unbuffered)*/ #ifndef _WIN32 if(!innobase_file_flush_method || - !strstr(innobase_file_flush_method, "O_DIRECT")) { - innobase_file_flush_method = + !strstr(innobase_file_flush_method, "O_DIRECT")) { + innobase_file_flush_method = srv_file_flush_method_str = (char*)"O_DIRECT"; - fprintf(stderr, "InnoDB: using O_DIRECT due to atomic writes.\n"); + fprintf(stderr, + "InnoDB: using O_DIRECT due to atomic " + "writes.\n"); } #endif #ifdef HAVE_POSIX_FALLOCATE - /* Due to a bug in directFS, using atomics needs - * posix_fallocate to extend the file - * pwrite() past end of the file won't work - */ + /* Due to a bug in directFS, using atomics needs + posix_fallocate() to extend the file, because pwrite() past the + end of the file won't work */ srv_use_posix_fallocate = TRUE; #endif } @@ -4544,7 +4577,6 @@ ha_innobase::open( dict_table_t* ib_table; char norm_name[1000]; THD* thd; - ulint retries = 0; char* is_part = NULL; ibool par_case_name_set = FALSE; char par_case_name[MAX_FULL_NAME_LEN + 1]; @@ -4584,17 +4616,13 @@ ha_innobase::open( upd_buf_size = 0; /* We look for pattern #P# to see if the table is partitioned - MySQL table. The retry logic for partitioned tables is a - workaround for http://bugs.mysql.com/bug.php?id=33349. Look - at support issue https://support.mysql.com/view.php?id=21080 - for more details. */ + MySQL table. */ #ifdef __WIN__ is_part = strstr(norm_name, "#p#"); #else is_part = strstr(norm_name, "#P#"); #endif /* __WIN__ */ -retry: /* Get pointer to a table object in InnoDB dictionary cache */ ib_table = dict_table_get(norm_name, TRUE); @@ -4611,7 +4639,7 @@ retry: share->ib_table = ib_table; if (NULL == ib_table) { - if (is_part && retries < 10) { + if (is_part) { /* MySQL partition engine hard codes the file name separator as "#P#". The text case is fixed even if lower_case_table_names is set to 1 or 2. This is true @@ -4654,11 +4682,7 @@ retry: ib_table = dict_table_get( par_case_name, FALSE); } - if (!ib_table) { - ++retries; - os_thread_sleep(100000); - goto retry; - } else { + if (ib_table) { #ifndef __WIN__ sql_print_warning("Partition table %s opened " "after converting to lower " @@ -4684,9 +4708,8 @@ retry: } if (is_part) { - sql_print_error("Failed to open table %s after " - "%lu attempts.\n", norm_name, - retries); + sql_print_error("Failed to open table %s.\n", + norm_name); } sql_print_error("Cannot find or open table %s from\n" @@ -6663,6 +6686,8 @@ ha_innobase::unlock_row(void) { DBUG_ENTER("ha_innobase::unlock_row"); + ut_ad(prebuilt->trx->state == TRX_ACTIVE); + /* Consistent read does not take any locks, thus there is nothing to unlock. */ @@ -8710,12 +8735,18 @@ innobase_rename_table( DEBUG_SYNC_C("innodb_rename_table_ready"); /* Serialize data dictionary operations with dictionary mutex: - no deadlocks can occur then in these operations */ + no deadlocks can occur then in these operations. Start the + transaction first to avoid a possible deadlock in the server. */ + trx_start_if_not_started(trx); if (lock_and_commit) { row_mysql_lock_data_dictionary(trx); } + /* Flag this transaction as a dictionary operation, so that + the data dictionary will be locked in crash recovery. */ + trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); + error = row_rename_table_for_mysql( norm_from, norm_to, trx, lock_and_commit); @@ -9268,9 +9299,11 @@ ha_innobase::info_low( prebuilt->trx->op_info = "updating table statistics"; - dict_update_statistics(ib_table, - FALSE /* update even if stats - are initialized */, called_from_analyze); + dict_update_statistics( + ib_table, + FALSE, /* update even if initialized */ + called_from_analyze, + FALSE /* update even if not changed too much */); prebuilt->trx->op_info = "returning various info to MySQL"; } @@ -12503,6 +12536,63 @@ innodb_change_buffering_update( *static_cast(save); } +#ifndef DBUG_OFF +static char* srv_buffer_pool_evict; + +/****************************************************************//** +Called on SET GLOBAL innodb_buffer_pool_evict=... +Handles some values specially, to evict pages from the buffer pool. +SET GLOBAL innodb_buffer_pool_evict='uncompressed' +evicts all uncompressed page frames of compressed tablespaces. */ +static +void +innodb_buffer_pool_evict_update( +/*============================*/ + THD* thd, /*!< in: thread handle */ + struct st_mysql_sys_var*var, /*!< in: pointer to system variable */ + void* var_ptr,/*!< out: ignored */ + const void* save) /*!< in: immediate result + from check function */ +{ + if (const char* op = *static_cast(save)) { + if (!strcmp(op, "uncompressed")) { + /* Evict all uncompressed pages of compressed + tables from the buffer pool. Keep the compressed + pages in the buffer pool. */ + + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool = &buf_pool_ptr[i]; + + //buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->LRU_list_mutex); + + for (buf_block_t* block = UT_LIST_GET_LAST( + buf_pool->unzip_LRU); + block != NULL; ) { + + buf_block_t* prev_block + = UT_LIST_GET_PREV(unzip_LRU, + block); + ut_ad(buf_block_get_state(block) + == BUF_BLOCK_FILE_PAGE); + ut_ad(block->in_unzip_LRU_list); + ut_ad(block->page.in_LRU_list); + + mutex_enter(&block->mutex); + buf_LRU_free_block(&block->page, + FALSE, FALSE); + mutex_exit(&block->mutex); + block = prev_block; + } + + mutex_exit(&buf_pool->LRU_list_mutex); + //buf_pool_mutex_exit(buf_pool); + } + } + } +} +#endif /* !DBUG_OFF */ + static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) { innodb_export_status(); @@ -12666,9 +12756,9 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite, static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Prevent partial page writes, via atomic writes." + "Prevent partial page writes, via atomic writes (beta). " "The option is used to prevent partial writes in case of a crash/poweroff, " - "as faster alternative to doublewrite buffer." + "as faster alternative to doublewrite buffer. " "Currently this option works only " "on Linux only with FusionIO device, and directFS filesystem.", NULL, NULL, FALSE); @@ -12890,6 +12980,13 @@ static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment, "Data file autoextend increment in megabytes", NULL, NULL, 8L, 1L, 1000L, 0); +#ifndef DBUG_OFF +static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict, + PLUGIN_VAR_RQCMDARG, + "Evict pages from the InnoDB buffer pool.", + NULL, innodb_buffer_pool_evict_update, ""); +#endif /* !DBUG_OFF */ + static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", @@ -13307,6 +13404,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(log_block_size), MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), +#ifndef DBUG_OFF + MYSQL_SYSVAR(buffer_pool_evict), +#endif /* !DBUG_OFF */ MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(buffer_pool_populate), MYSQL_SYSVAR(buffer_pool_instances), @@ -13607,6 +13707,58 @@ test_innobase_convert_name() #endif /* UNIV_COMPILE_TEST_FUNCS */ +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. */ +extern "C" +uint +innobase_convert_to_filename_charset( +/*=================================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + uint rlen; + CHARSET_INFO* cs_to = &my_charset_filename; + CHARSET_INFO* cs_from = system_charset_info; + + rlen = strconvert(cs_from, from, cs_to, to, len, &errors); + + if (errors) { + fprintf(stderr, "InnoDB: There was a problem in converting" + "'%s' in charset %s to charset %s", from, cs_from->name, + cs_to->name); + } + + return(rlen); +} + +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. */ +extern "C" +uint +innobase_convert_to_system_charset( +/*===============================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len, /* in: length of 'to', in bytes */ + uint* errors) /* out: error return */ +{ + uint rlen; + CHARSET_INFO* cs1 = &my_charset_filename; + CHARSET_INFO* cs2 = system_charset_info; + + rlen = strconvert(cs1, from, cs2, to, len, errors); + + if (*errors) { + fprintf(stderr, "InnoDB: There was a problem in converting" + "'%s' in charset %s to charset %s", from, cs1->name, + cs2->name); + } + + return(rlen); +} + /**************************************************************************** * DS-MRR implementation diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index d64a95a969e..ccbf5c7dbe7 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -53,7 +53,7 @@ extern "C" { #include "dict0mem.h" #include "dict0types.h" #include "ha_prototypes.h" /* for innobase_convert_name() */ -#include "srv0srv.h" /* for srv_track_changed_pages */ +#include "srv0srv.h" /* for srv_max_changed_pages */ #include "srv0start.h" /* for srv_was_started */ #include "trx0i_s.h" #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */ @@ -2273,6 +2273,7 @@ i_s_innodb_buffer_stats_fill_table( buf_pool_info_t* pool_info; DBUG_ENTER("i_s_innodb_buffer_fill_general"); + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); /* Only allow the PROCESS privilege holder to access the stats */ if (check_global_access(thd, PROCESS_ACL, true)) { @@ -2883,6 +2884,7 @@ i_s_innodb_fill_buffer_pool( mem_heap_t* heap; DBUG_ENTER("i_s_innodb_fill_buffer_pool"); + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); heap = mem_heap_create(10000); @@ -2923,7 +2925,8 @@ i_s_innodb_fill_buffer_pool( i_s_innodb_buffer_page_get_info( &block->page, pool_id, block_id, info_buffer + num_page); - mutex_exit(block_mutex); + if (block_mutex) + mutex_exit(block_mutex); block_id++; num_page++; } @@ -3443,7 +3446,6 @@ i_s_innodb_fill_buffer_lru( mutex_t* block_mutex; DBUG_ENTER("i_s_innodb_fill_buffer_lru"); - RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); /* Obtain buf_pool mutex before allocate info_buffer, since @@ -7332,6 +7334,7 @@ i_s_innodb_changed_pages_fill( ib_uint64_t output_rows_num = 0UL; ib_uint64_t max_lsn = IB_ULONGLONG_MAX; ib_uint64_t min_lsn = 0ULL; + int ret = 0; DBUG_ENTER("i_s_innodb_changed_pages_fill"); @@ -7343,10 +7346,6 @@ i_s_innodb_changed_pages_fill( RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - if (!srv_track_changed_pages) { - DBUG_RETURN(0); - } - if (cond) { limit_lsn_range_from_condition(table, cond, &min_lsn, &max_lsn); @@ -7422,8 +7421,13 @@ i_s_innodb_changed_pages_fill( ++output_rows_num; } + if (i.failed) { + my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0)); + ret = 1; + } + log_online_bitmap_iterator_release(&i); - DBUG_RETURN(0); + DBUG_RETURN(ret); } static diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c index 96c264b32b4..c79740a947d 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.c +++ b/storage/xtradb/ibuf/ibuf0ibuf.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -4319,7 +4319,7 @@ Deletes from ibuf the record on which pcur is positioned. If we have to resort to a pessimistic delete, this function commits mtr and closes the cursor. @return TRUE if mtr was committed and pcur closed in this operation */ -static +static __attribute__((warn_unused_result)) ibool ibuf_delete_rec( /*============*/ @@ -4625,6 +4625,12 @@ ibuf_merge_or_delete_for_page( loop: ibuf_mtr_start(&mtr); + /* Position pcur in the insert buffer at the first entry for this + index page */ + btr_pcur_open_on_user_rec( + ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF, + &pcur, &mtr); + if (block) { ibool success; @@ -4643,12 +4649,6 @@ loop: buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); } - /* Position pcur in the insert buffer at the first entry for this - index page */ - btr_pcur_open_on_user_rec( - ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF, - &pcur, &mtr); - if (!btr_pcur_is_on_user_rec(&pcur)) { ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr)); @@ -4733,6 +4733,16 @@ loop: == page_no); ut_ad(ibuf_rec_get_space(&mtr, rec) == space); + /* Mark the change buffer record processed, + so that it will not be merged again in case + the server crashes between the following + mtr_commit() and the subsequent mtr_commit() + of deleting the change buffer record. */ + + btr_cur_set_deleted_flag_for_ibuf( + btr_pcur_get_rec(&pcur), NULL, + TRUE, &mtr); + btr_pcur_store_position(&pcur, &mtr); ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr); @@ -4781,6 +4791,7 @@ loop: /* Deletion was pessimistic and mtr was committed: we start from the beginning again */ + ut_ad(mtr.state == MTR_COMMITTED); goto loop; } else if (btr_pcur_is_after_last_on_page(&pcur)) { ibuf_mtr_commit(&mtr); @@ -4911,6 +4922,7 @@ loop: /* Deletion was pessimistic and mtr was committed: we start from the beginning again */ + ut_ad(mtr.state == MTR_COMMITTED); goto loop; } diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h index f00a06c8805..233231e4cab 100644 --- a/storage/xtradb/include/buf0buf.h +++ b/storage/xtradb/include/buf0buf.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -684,9 +684,12 @@ UNIV_INTERN ibool buf_page_is_corrupted( /*==================*/ + ibool check_lsn, /*!< in: TRUE if we need to check + and complain about the LSN */ const byte* read_buf, /*!< in: a database page */ - ulint zip_size); /*!< in: size of compressed page; + ulint zip_size) /*!< in: size of compressed page; 0 for uncompressed pages */ + __attribute__((warn_unused_result)); #ifndef UNIV_HOTBACKUP /**********************************************************************//** Gets the space id, page offset, and byte offset within page of a diff --git a/storage/xtradb/include/db0err.h b/storage/xtradb/include/db0err.h index 3a4c8a54016..4d0e3051fe6 100644 --- a/storage/xtradb/include/db0err.h +++ b/storage/xtradb/include/db0err.h @@ -114,6 +114,7 @@ enum db_err { DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */ DB_TABLE_IN_FK_CHECK, /* table is being used in foreign key check */ + DB_IDENTIFIER_TOO_LONG, /* Identifier name too long */ /* The following are partial failure codes */ DB_FAIL = 1000, diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index 1dd0b3f5082..f175f2c6194 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1124,6 +1124,18 @@ ulint dict_index_calc_min_rec_len( /*========================*/ const dict_index_t* index); /*!< in: index */ + +/** Calculate new statistics if 1 / 16 of table has been modified +since the last time a statistics batch was run. +We calculate statistics at most every 16th round, since we may have +a counter table which is very small and updated very often. +@param t table +@return true if the table has changed too much and stats need to be +recalculated +*/ +#define DICT_TABLE_CHANGED_TOO_MUCH(t) \ + ((ib_int64_t) (t)->stat_modified_counter > 16 + (t)->stat_n_rows / 16) + /*********************************************************************//** Calculates new estimates for table and index statistics. The statistics are used in query optimization. */ @@ -1132,11 +1144,15 @@ void dict_update_statistics( /*===================*/ dict_table_t* table, /*!< in/out: table */ - ibool only_calc_if_missing_stats, /*!< in: only + ibool only_calc_if_missing_stats,/*!< in: only update/recalc the stats if they have not been initialized yet, otherwise do nothing */ - ibool sync); + ibool sync, + ibool only_calc_if_changed_too_much);/*!< in: only + update/recalc the stats if the table + has been changed too much since the + last stats update/recalc */ /*********************************************************************//** */ UNIV_INTERN diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index 630942ae2ac..4e6713d15c8 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -127,7 +127,7 @@ This could result in rescursive calls and out of stack error eventually. DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads, when exceeded, the child table will not be loaded. It will be loaded when the foreign constraint check needs to be run. */ -#define DICT_FK_MAX_RECURSIVE_LOAD 255 +#define DICT_FK_MAX_RECURSIVE_LOAD 20 /** Similarly, when tables are chained together with foreign key constraints with on cascading delete/update clause, delete from parent table could @@ -607,7 +607,13 @@ struct dict_table_struct{ /*!< flag: TRUE if the maximum length of a single row exceeds BIG_ROW_SIZE; initialized in dict_table_add_to_cache() */ - /** Statistics for query optimization */ + /** Statistics for query optimization. + The following stat_* members are usually + protected by dict_table_stats_lock(). In + some exceptional cases (performance critical + code paths) we access or modify stat_n_rows + and stat_modified_counter without any + protection. */ /* @{ */ unsigned stat_initialized:1; /*!< TRUE if statistics have been calculated the first time diff --git a/storage/xtradb/include/dict0types.h b/storage/xtradb/include/dict0types.h index f0a05a38070..8e3a04f7956 100644 --- a/storage/xtradb/include/dict0types.h +++ b/storage/xtradb/include/dict0types.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -58,4 +58,7 @@ enum dict_err_ignore { typedef enum dict_err_ignore dict_err_ignore_t; +#define TEMP_TABLE_PREFIX "#sql" +#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX + #endif diff --git a/storage/xtradb/include/dyn0dyn.h b/storage/xtradb/include/dyn0dyn.h index 121a5946ac7..62ed862e82c 100644 --- a/storage/xtradb/include/dyn0dyn.h +++ b/storage/xtradb/include/dyn0dyn.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -47,15 +47,17 @@ UNIV_INLINE dyn_array_t* dyn_array_create( /*=============*/ - dyn_array_t* arr); /*!< in: pointer to a memory buffer of + dyn_array_t* arr) /*!< in/out memory buffer of size sizeof(dyn_array_t) */ + __attribute__((nonnull)); /************************************************************//** Frees a dynamic array. */ UNIV_INLINE void dyn_array_free( /*===========*/ - dyn_array_t* arr); /*!< in: dyn array */ + dyn_array_t* arr) /*!< in,own: dyn array */ + __attribute__((nonnull)); /*********************************************************************//** Makes room on top of a dyn array and returns a pointer to a buffer in it. After copying the elements, the caller must close the buffer using @@ -66,8 +68,9 @@ byte* dyn_array_open( /*===========*/ dyn_array_t* arr, /*!< in: dynamic array */ - ulint size); /*!< in: size in bytes of the buffer; MUST be + ulint size) /*!< in: size in bytes of the buffer; MUST be smaller than DYN_ARRAY_DATA_SIZE! */ + __attribute__((nonnull, warn_unused_result)); /*********************************************************************//** Closes the buffer returned by dyn_array_open. */ UNIV_INLINE @@ -75,7 +78,8 @@ void dyn_array_close( /*============*/ dyn_array_t* arr, /*!< in: dynamic array */ - byte* ptr); /*!< in: buffer space from ptr up was not used */ + const byte* ptr) /*!< in: end of used space */ + __attribute__((nonnull)); /*********************************************************************//** Makes room on top of a dyn array and returns a pointer to the added element. The caller must copy the element to @@ -85,8 +89,9 @@ UNIV_INLINE void* dyn_array_push( /*===========*/ - dyn_array_t* arr, /*!< in: dynamic array */ - ulint size); /*!< in: size in bytes of the element */ + dyn_array_t* arr, /*!< in/out: dynamic array */ + ulint size) /*!< in: size in bytes of the element */ + __attribute__((nonnull, warn_unused_result)); /************************************************************//** Returns pointer to an element in dyn array. @return pointer to element */ @@ -94,9 +99,10 @@ UNIV_INLINE void* dyn_array_get_element( /*==================*/ - dyn_array_t* arr, /*!< in: dyn array */ - ulint pos); /*!< in: position of element as bytes - from array start */ + const dyn_array_t* arr, /*!< in: dyn array */ + ulint pos) /*!< in: position of element + in bytes from array start */ + __attribute__((nonnull, warn_unused_result)); /************************************************************//** Returns the size of stored data in a dyn array. @return data size in bytes */ @@ -104,30 +110,33 @@ UNIV_INLINE ulint dyn_array_get_data_size( /*====================*/ - dyn_array_t* arr); /*!< in: dyn array */ + const dyn_array_t* arr) /*!< in: dyn array */ + __attribute__((nonnull, warn_unused_result, pure)); /************************************************************//** -Gets the first block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_first_block( -/*======================*/ - dyn_array_t* arr); /*!< in: dyn array */ +Gets the first block in a dyn array. +@param arr dyn array +@return first block */ +#define dyn_array_get_first_block(arr) (arr) /************************************************************//** -Gets the last block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_last_block( -/*=====================*/ - dyn_array_t* arr); /*!< in: dyn array */ +Gets the last block in a dyn array. +@param arr dyn array +@return last block */ +#define dyn_array_get_last_block(arr) \ + ((arr)->heap ? UT_LIST_GET_LAST((arr)->base) : (arr)) /********************************************************************//** Gets the next block in a dyn array. -@return pointer to next, NULL if end of list */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_next_block( -/*=====================*/ - dyn_array_t* arr, /*!< in: dyn array */ - dyn_block_t* block); /*!< in: dyn array block */ +@param arr dyn array +@param block dyn array block +@return pointer to next, NULL if end of list */ +#define dyn_array_get_next_block(arr, block) \ + ((arr)->heap ? UT_LIST_GET_NEXT(list, block) : NULL) +/********************************************************************//** +Gets the previous block in a dyn array. +@param arr dyn array +@param block dyn array block +@return pointer to previous, NULL if end of list */ +#define dyn_array_get_prev_block(arr, block) \ + ((arr)->heap ? UT_LIST_GET_PREV(list, block) : NULL) /********************************************************************//** Gets the number of used bytes in a dyn array block. @return number of bytes used */ @@ -135,7 +144,8 @@ UNIV_INLINE ulint dyn_block_get_used( /*===============*/ - dyn_block_t* block); /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ + __attribute__((nonnull, warn_unused_result, pure)); /********************************************************************//** Gets pointer to the start of data in a dyn array block. @return pointer to data */ @@ -143,16 +153,18 @@ UNIV_INLINE byte* dyn_block_get_data( /*===============*/ - dyn_block_t* block); /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ + __attribute__((nonnull, warn_unused_result, pure)); /********************************************************//** Pushes n bytes to a dyn array. */ UNIV_INLINE void dyn_push_string( /*============*/ - dyn_array_t* arr, /*!< in: dyn array */ + dyn_array_t* arr, /*!< in/out: dyn array */ const byte* str, /*!< in: string to write */ - ulint len); /*!< in: string length */ + ulint len) /*!< in: string length */ + __attribute__((nonnull)); /*#################################################################*/ diff --git a/storage/xtradb/include/dyn0dyn.ic b/storage/xtradb/include/dyn0dyn.ic index 110e674abff..177877ed1fd 100644 --- a/storage/xtradb/include/dyn0dyn.ic +++ b/storage/xtradb/include/dyn0dyn.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -35,56 +35,8 @@ UNIV_INTERN dyn_block_t* dyn_array_add_block( /*================*/ - dyn_array_t* arr); /*!< in: dyn array */ - - -/************************************************************//** -Gets the first block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_first_block( -/*======================*/ - dyn_array_t* arr) /*!< in: dyn array */ -{ - return(arr); -} - -/************************************************************//** -Gets the last block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_last_block( -/*=====================*/ - dyn_array_t* arr) /*!< in: dyn array */ -{ - if (arr->heap == NULL) { - - return(arr); - } - - return(UT_LIST_GET_LAST(arr->base)); -} - -/********************************************************************//** -Gets the next block in a dyn array. -@return pointer to next, NULL if end of list */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_next_block( -/*=====================*/ - dyn_array_t* arr, /*!< in: dyn array */ - dyn_block_t* block) /*!< in: dyn array block */ -{ - ut_ad(arr && block); - - if (arr->heap == NULL) { - ut_ad(arr == block); - - return(NULL); - } - - return(UT_LIST_GET_NEXT(list, block)); -} + dyn_array_t* arr) /*!< in/out: dyn array */ + __attribute__((nonnull, warn_unused_result)); /********************************************************************//** Gets the number of used bytes in a dyn array block. @@ -93,7 +45,7 @@ UNIV_INLINE ulint dyn_block_get_used( /*===============*/ - dyn_block_t* block) /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ { ut_ad(block); @@ -107,11 +59,11 @@ UNIV_INLINE byte* dyn_block_get_data( /*===============*/ - dyn_block_t* block) /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ { ut_ad(block); - return(block->data); + return((byte*) block->data); } /*********************************************************************//** @@ -121,7 +73,7 @@ UNIV_INLINE dyn_array_t* dyn_array_create( /*=============*/ - dyn_array_t* arr) /*!< in: pointer to a memory buffer of + dyn_array_t* arr) /*!< in/out: memory buffer of size sizeof(dyn_array_t) */ { ut_ad(arr); @@ -132,10 +84,9 @@ dyn_array_create( arr->heap = NULL; arr->used = 0; -#ifdef UNIV_DEBUG - arr->buf_end = 0; - arr->magic_n = DYN_BLOCK_MAGIC_N; -#endif + ut_d(arr->buf_end = 0); + ut_d(arr->magic_n = DYN_BLOCK_MAGIC_N); + return(arr); } @@ -151,9 +102,7 @@ dyn_array_free( mem_heap_free(arr->heap); } -#ifdef UNIV_DEBUG - arr->magic_n = 0; -#endif + ut_d(arr->magic_n = 0); } /*********************************************************************//** @@ -164,7 +113,7 @@ UNIV_INLINE void* dyn_array_push( /*===========*/ - dyn_array_t* arr, /*!< in: dynamic array */ + dyn_array_t* arr, /*!< in/out: dynamic array */ ulint size) /*!< in: size in bytes of the element */ { dyn_block_t* block; @@ -176,24 +125,23 @@ dyn_array_push( ut_ad(size); block = arr; - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { /* Get the last array block */ block = dyn_array_get_last_block(arr); - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { block = dyn_array_add_block(arr); - used = block->used; } } + used = block->used; + block->used = used + size; ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); - return((block->data) + used); + return(block->data + used); } /*********************************************************************//** @@ -210,7 +158,6 @@ dyn_array_open( smaller than DYN_ARRAY_DATA_SIZE! */ { dyn_block_t* block; - ulint used; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -218,28 +165,23 @@ dyn_array_open( ut_ad(size); block = arr; - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { /* Get the last array block */ block = dyn_array_get_last_block(arr); - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { block = dyn_array_add_block(arr); - used = block->used; ut_a(size <= DYN_ARRAY_DATA_SIZE); } } ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); -#ifdef UNIV_DEBUG ut_ad(arr->buf_end == 0); + ut_d(arr->buf_end = block->used + size); - arr->buf_end = used + size; -#endif - return((block->data) + used); + return(block->data + block->used); } /*********************************************************************//** @@ -248,8 +190,8 @@ UNIV_INLINE void dyn_array_close( /*============*/ - dyn_array_t* arr, /*!< in: dynamic array */ - byte* ptr) /*!< in: buffer space from ptr up was not used */ + dyn_array_t* arr, /*!< in/out: dynamic array */ + const byte* ptr) /*!< in: end of used space */ { dyn_block_t* block; @@ -264,9 +206,7 @@ dyn_array_close( ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); -#ifdef UNIV_DEBUG - arr->buf_end = 0; -#endif + ut_d(arr->buf_end = 0); } /************************************************************//** @@ -276,12 +216,11 @@ UNIV_INLINE void* dyn_array_get_element( /*==================*/ - dyn_array_t* arr, /*!< in: dyn array */ - ulint pos) /*!< in: position of element as bytes - from array start */ + const dyn_array_t* arr, /*!< in: dyn array */ + ulint pos) /*!< in: position of element + in bytes from array start */ { - dyn_block_t* block; - ulint used; + const dyn_block_t* block; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -290,21 +229,23 @@ dyn_array_get_element( block = dyn_array_get_first_block(arr); if (arr->heap != NULL) { - used = dyn_block_get_used(block); + for (;;) { + ulint used = dyn_block_get_used(block); + + if (pos < used) { + break; + } - while (pos >= used) { pos -= used; block = UT_LIST_GET_NEXT(list, block); ut_ad(block); - - used = dyn_block_get_used(block); } } ut_ad(block); ut_ad(dyn_block_get_used(block) >= pos); - return(block->data + pos); + return((byte*) block->data + pos); } /************************************************************//** @@ -314,10 +255,10 @@ UNIV_INLINE ulint dyn_array_get_data_size( /*====================*/ - dyn_array_t* arr) /*!< in: dyn array */ + const dyn_array_t* arr) /*!< in: dyn array */ { - dyn_block_t* block; - ulint sum = 0; + const dyn_block_t* block; + ulint sum = 0; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -344,7 +285,7 @@ UNIV_INLINE void dyn_push_string( /*============*/ - dyn_array_t* arr, /*!< in: dyn array */ + dyn_array_t* arr, /*!< in/out: dyn array */ const byte* str, /*!< in: string to write */ ulint len) /*!< in: string length */ { diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 2149d0aadca..881623b30cf 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -328,10 +328,12 @@ fil_write_flushed_lsn_to_data_files( ulint arch_log_no); /*!< in: latest archived log file number */ /*******************************************************************//** -Reads the flushed lsn and arch no fields from a data file at database -startup. */ +Reads the flushed lsn, arch no, and tablespace flag fields from a data +file at database startup. +@retval NULL on success, or if innodb_force_recovery is set +@return pointer to an error message string */ UNIV_INTERN -void +const char* fil_read_first_page( /*================*/ os_file_t data_file, /*!< in: open data file */ @@ -347,8 +349,9 @@ fil_read_first_page( #endif /* UNIV_LOG_ARCHIVE */ ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed lsn values in data files */ - ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed + ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed lsn values in data files */ + __attribute__((warn_unused_result)); /*******************************************************************//** Increments the count of pending operation, if space is not being deleted. @return TRUE if being deleted, and operation should be skipped */ diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 51e331c3b5d..d8531984815 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -323,4 +323,35 @@ thd_merge_sort_block_size( void* thd); /*!< in: thread handle (THD*), or NULL to query the global merge_sort_block_size */ +/********************************************************************** +Check if the length of the identifier exceeds the maximum allowed. +The input to this function is an identifier in charset my_charset_filename. +return true when length of identifier is too long. */ +UNIV_INTERN +my_bool +innobase_check_identifier_length( +/*=============================*/ + const char* id); /* in: identifier to check. it must belong + to charset my_charset_filename */ + +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. */ +uint +innobase_convert_to_system_charset( +/*===============================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len, /* in: length of 'to', in bytes */ + uint* errors); /* out: error return */ + +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. */ +uint +innobase_convert_to_filename_charset( +/*=================================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len); /* in: length of 'to', in bytes */ + + #endif diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h index 85285a77084..424c8cd7d1d 100644 --- a/storage/xtradb/include/log0log.h +++ b/storage/xtradb/include/log0log.h @@ -415,7 +415,9 @@ log_group_read_log_seg( byte* buf, /*!< in: buffer where to read */ log_group_t* group, /*!< in: log group */ ib_uint64_t start_lsn, /*!< in: read area start */ - ib_uint64_t end_lsn); /*!< in: read area end */ + ib_uint64_t end_lsn, /*!< in: read area end */ + ibool release_mutex); /*!< in: whether the log_sys->mutex + should be released before the read */ /******************************************************//** Writes a buffer to a log file group. */ UNIV_INTERN diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h index 999a317780e..a20eef57d7a 100644 --- a/storage/xtradb/include/log0online.h +++ b/storage/xtradb/include/log0online.h @@ -159,6 +159,8 @@ struct log_online_bitmap_file_range_struct { /** Struct for an iterator through all bits of changed pages bitmap blocks */ struct log_bitmap_iterator_struct { + ibool failed; /*!< Has the iteration + stopped prematurely */ log_online_bitmap_file_range_t in_files; /*!< The bitmap files for this iterator */ size_t in_i; /*!< Currently read diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h index c51632e0ed5..031fccd300c 100644 --- a/storage/xtradb/include/mtr0mtr.h +++ b/storage/xtradb/include/mtr0mtr.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -295,9 +295,10 @@ UNIV_INTERN void mtr_memo_release( /*=============*/ - mtr_t* mtr, /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction */ void* object, /*!< in: object */ - ulint type); /*!< in: object type: MTR_MEMO_S_LOCK, ... */ + ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ + __attribute__((nonnull)); #ifdef UNIV_DEBUG # ifndef UNIV_HOTBACKUP /**********************************************************//** @@ -309,7 +310,8 @@ mtr_memo_contains( /*==============*/ mtr_t* mtr, /*!< in: mtr */ const void* object, /*!< in: object to search */ - ulint type); /*!< in: type of object */ + ulint type) /*!< in: type of object */ + __attribute__((warn_unused_result, nonnull)); /**********************************************************//** Checks if memo contains the given page. diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h index 05403a8e752..e6c70edbd8f 100644 --- a/storage/xtradb/include/os0file.h +++ b/storage/xtradb/include/os0file.h @@ -21,7 +21,7 @@ Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ***********************************************************************/ @@ -76,15 +76,19 @@ extern ulint os_n_pending_writes; #endif #ifdef __WIN__ +#define SRV_PATH_SEPARATOR '\\' /** File handle */ # define os_file_t HANDLE +# define os_file_invalid INVALID_HANDLE_VALUE /** Convert a C file descriptor to a native file handle @param fd file descriptor @return native file handle */ # define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd) #else +#define SRV_PATH_SEPARATOR '/' /** File handle */ typedef int os_file_t; +# define os_file_invalid (-1) /** Convert a C file descriptor to a native file handle @param fd file descriptor @return native file handle */ @@ -819,7 +823,6 @@ pfs_os_file_rename_func( ulint src_line);/*!< in: line where the func invoked */ #endif /* UNIV_PFS_IO */ -#ifdef UNIV_HOTBACKUP /***********************************************************************//** Closes a file handle. @return TRUE if success */ @@ -828,7 +831,6 @@ ibool os_file_close_no_error_handling( /*============================*/ os_file_t file); /*!< in, own: handle to a file */ -#endif /* UNIV_HOTBACKUP */ /***********************************************************************//** Gets a file size. @return TRUE if success */ diff --git a/storage/xtradb/include/page0zip.ic b/storage/xtradb/include/page0zip.ic index 75cc7a9fcc4..9e9dda90936 100644 --- a/storage/xtradb/include/page0zip.ic +++ b/storage/xtradb/include/page0zip.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -188,8 +188,8 @@ page_zip_rec_needs_ext( one record on an empty leaf page. Subtract 1 byte for the encoded heap number. Check also the available space on the uncompressed page. */ - return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2) - >= (page_zip_empty_size(n_fields, zip_size) - 1) + return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1) + >= page_zip_empty_size(n_fields, zip_size) || rec_size >= page_get_free_space_of_empty(TRUE) / 2); } @@ -229,9 +229,7 @@ ibool page_zip_get_trailer_len( /*=====================*/ const page_zip_des_t* page_zip,/*!< in: compressed page */ - ibool is_clust,/*!< in: TRUE if clustered index */ - ulint* entry_size)/*!< out: size of the uncompressed - portion of a user record */ + ibool is_clust)/*!< in: TRUE if clustered index */ { ulint uncompressed_size; @@ -250,10 +248,6 @@ page_zip_get_trailer_len( ut_ad(!page_zip->n_blobs); } - if (entry_size) { - *entry_size = uncompressed_size; - } - return((page_dir_get_n_heap(page_zip->data) - 2) * uncompressed_size + page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE); @@ -270,11 +264,9 @@ page_zip_max_ins_size( const page_zip_des_t* page_zip,/*!< in: compressed page */ ibool is_clust)/*!< in: TRUE if clustered index */ { - ulint uncompressed_size; ulint trailer_len; - trailer_len = page_zip_get_trailer_len(page_zip, is_clust, - &uncompressed_size); + trailer_len = page_zip_get_trailer_len(page_zip, is_clust); /* When a record is created, a pointer may be added to the dense directory. @@ -283,7 +275,7 @@ page_zip_max_ins_size( Also the BLOB pointers will be allocated from there, but we may as well count them in the length of the record. */ - trailer_len += uncompressed_size; + trailer_len += PAGE_ZIP_DIR_SLOT_SIZE; return((lint) page_zip_get_size(page_zip) - trailer_len - page_zip->m_end @@ -303,13 +295,11 @@ page_zip_available( ulint create) /*!< in: nonzero=add the record to the heap */ { - ulint uncompressed_size; ulint trailer_len; ut_ad(length > REC_N_NEW_EXTRA_BYTES); - trailer_len = page_zip_get_trailer_len(page_zip, is_clust, - &uncompressed_size); + trailer_len = page_zip_get_trailer_len(page_zip, is_clust); /* Subtract the fixed extra bytes and add the maximum space needed for identifying the record (encoded heap_no). */ @@ -323,7 +313,7 @@ page_zip_available( Also the BLOB pointers will be allocated from there, but we may as well count them in the length of the record. */ - trailer_len += uncompressed_size; + trailer_len += PAGE_ZIP_DIR_SLOT_SIZE; } return(UNIV_LIKELY(length diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 53dbf21e455..09c0b0666c7 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -297,6 +297,9 @@ extern ulint srv_n_rows_updated; extern ulint srv_n_rows_deleted; extern ulint srv_n_rows_read; +extern ulint srv_read_views_memory; +extern ulint srv_descriptors_memory; + extern ibool srv_print_innodb_monitor; extern ibool srv_print_innodb_lock_monitor; extern ibool srv_print_innodb_tablespace_monitor; @@ -901,6 +904,8 @@ struct export_var_struct{ ulint innodb_rows_updated; /*!< srv_n_rows_updated */ ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */ ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */ + ulint innodb_read_views_memory; /*!< srv_read_views_memory */ + ulint innodb_descriptors_memory; /*!< srv_descriptors_memory */ ib_int64_t innodb_s_lock_os_waits; ib_int64_t innodb_s_lock_spin_rounds; ib_int64_t innodb_s_lock_spin_waits; diff --git a/storage/xtradb/include/ut0dbg.h b/storage/xtradb/include/ut0dbg.h index ce6dcb63049..4913b357768 100644 --- a/storage/xtradb/include/ut0dbg.h +++ b/storage/xtradb/include/ut0dbg.h @@ -55,49 +55,8 @@ ut_dbg_assertion_failed( ulint line) /*!< in: line number of the assertion */ UNIV_COLD __attribute__((nonnull(2))); - -#define UT_DBG_USE_ABORT - - -#ifndef UT_DBG_USE_ABORT -/** A null pointer that will be dereferenced to trigger a memory trap */ -extern ulint* ut_dbg_null_ptr; -#endif - -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) -/** If this is set to TRUE by ut_dbg_assertion_failed(), all threads -will stop at the next ut_a() or ut_ad(). */ -extern ibool ut_dbg_stop_threads; - -/*************************************************************//** -Stop a thread after assertion failure. */ -UNIV_INTERN -void -ut_dbg_stop_thread( -/*===============*/ - const char* file, - ulint line); -#endif - -#ifdef UT_DBG_USE_ABORT /** Abort the execution. */ -#ifdef _WIN32 -# define UT_DBG_PANIC __debugbreak() -#else # define UT_DBG_PANIC abort() -#endif -/** Stop threads (null operation) */ -# define UT_DBG_STOP do {} while (0) -#else /* UT_DBG_USE_ABORT */ -/** Abort the execution. */ -# define UT_DBG_PANIC \ - if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL -/** Stop threads in ut_a(). */ -# define UT_DBG_STOP do \ - if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \ - ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \ - } while (0) -#endif /* UT_DBG_USE_ABORT */ /** Abort execution if EXPR does not evaluate to nonzero. @param EXPR assertion expression that should hold */ @@ -107,7 +66,6 @@ ut_dbg_stop_thread( __FILE__, (ulint) __LINE__); \ UT_DBG_PANIC; \ } \ - UT_DBG_STOP; \ } while (0) /** Abort execution. */ diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index f4c991d4fe9..70df6f1a66a 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -2005,6 +2005,8 @@ lock_rec_lock_fast( || mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); + DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL);); + lock = lock_rec_get_first_on_page(block); trx = thr_get_trx(thr); @@ -2082,6 +2084,8 @@ lock_rec_lock_slow( trx = thr_get_trx(thr); + DBUG_EXECUTE_IF("innodb_report_deadlock", return(DB_DEADLOCK);); + lock = lock_rec_has_expl(mode, block, heap_no, trx); if (lock) { if (lock->type_mode & LOCK_CONV_BY_OTHER) { @@ -4145,6 +4149,7 @@ lock_rec_unlock( ut_ad(trx && rec); ut_ad(block->frame == page_align(rec)); + ut_ad(trx->state == TRX_ACTIVE); heap_no = page_rec_get_heap_no(rec); @@ -5002,6 +5007,7 @@ lock_rec_validate_page( { const lock_t* lock; const rec_t* rec; + dict_index_t* index; ulint nth_lock = 0; ulint nth_bit = 0; ulint i; @@ -5051,6 +5057,7 @@ loop: if (i == 1 || lock_rec_get_nth_bit(lock, i)) { + index = lock->index; rec = page_find_rec_with_heap_no(block->frame, i); ut_a(rec); offsets = rec_get_offsets(rec, lock->index, offsets, @@ -5067,7 +5074,7 @@ loop: check WILL break the latching order and may cause a deadlock of threads. */ - lock_rec_queue_validate(block, rec, lock->index, + lock_rec_queue_validate(block, rec, index, offsets); lock_mutex_enter_kernel(); diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c index e51ac7c4d5d..9ff8c2448d4 100644 --- a/storage/xtradb/log/log0log.c +++ b/storage/xtradb/log/log0log.c @@ -2390,7 +2390,8 @@ loop: } /******************************************************//** -Reads a specified log segment to a buffer. */ +Reads a specified log segment to a buffer. Optionally releases the log mutex +before the I/O. */ UNIV_INTERN void log_group_read_log_seg( @@ -2399,7 +2400,9 @@ log_group_read_log_seg( byte* buf, /*!< in: buffer where to read */ log_group_t* group, /*!< in: log group */ ib_uint64_t start_lsn, /*!< in: read area start */ - ib_uint64_t end_lsn) /*!< in: read area end */ + ib_uint64_t end_lsn, /*!< in: read area end */ + ibool release_mutex) /*!< in: whether the log_sys->mutex + should be released before the read */ { ulint len; ulint source_offset; @@ -2429,6 +2432,10 @@ loop: log_sys->n_log_ios++; + if (release_mutex) { + mutex_exit(&(log_sys->mutex)); + } + fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, 0, source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE, len, buf, NULL); @@ -2438,6 +2445,9 @@ loop: if (start_lsn != end_lsn) { + if (release_mutex) { + mutex_enter(&(log_sys->mutex)); + } goto loop; } } @@ -2929,7 +2939,7 @@ arch_none: log_group_read_log_seg(LOG_ARCHIVE, log_sys->archive_buf, UT_LIST_GET_FIRST(log_sys->log_groups), - start_lsn, limit_lsn); + start_lsn, limit_lsn, FALSE); mutex_exit(&(log_sys->mutex)); diff --git a/storage/xtradb/log/log0online.c b/storage/xtradb/log/log0online.c index be0a9708b8c..6d7cb928d9c 100644 --- a/storage/xtradb/log/log0online.c +++ b/storage/xtradb/log/log0online.c @@ -43,8 +43,8 @@ UNIV_INTERN mysql_pfs_key_t log_bmp_sys_mutex_key; /** Log parsing and bitmap output data structure */ struct log_bitmap_struct { - byte read_buf[FOLLOW_SCAN_SIZE]; - /*!< log read buffer */ + byte* read_buf_ptr; /*!< Unaligned log read buffer */ + byte* read_buf; /*!< log read buffer */ byte parse_buf[RECV_PARSING_BUF_SIZE]; /*!< log parse buffer */ byte* parse_buf_end; /*!< parse buffer position where the @@ -53,6 +53,8 @@ struct log_bitmap_struct { parsed, it points to the start, otherwise points immediatelly past the end of the incomplete log record. */ + char bmp_file_home[FN_REFLEN]; + /*!< directory for bitmap files */ log_online_bitmap_file_t out; /*!< The current bitmap file */ ulint out_seq_num; /*!< the bitmap file sequence number */ ib_uint64_t start_lsn; /*!< the LSN of the next unparsed @@ -490,9 +492,8 @@ log_online_make_bitmap_name( ib_uint64_t start_lsn) /*!< in: the start LSN name part */ { ut_snprintf(log_bmp_sys->out.name, FN_REFLEN, bmp_file_name_template, - srv_data_home, bmp_file_name_stem, + log_bmp_sys->bmp_file_home, bmp_file_name_stem, log_bmp_sys->out_seq_num, start_lsn); - } /*********************************************************************//** @@ -509,7 +510,8 @@ log_online_should_overwrite( /* Currently, it's OK to overwrite 0-sized files only */ success = os_file_get_status(path, &file_info); - return success && file_info.size == 0LL; + return success && file_info.type == OS_FILE_TYPE_FILE + && file_info.size == 0LL; } /*********************************************************************//** @@ -525,7 +527,7 @@ log_online_start_bitmap_file(void) /* Check for an old file that should be deleted first */ if (log_online_should_overwrite(log_bmp_sys->out.name)) { - success = os_file_delete(log_bmp_sys->out.name); + success = os_file_delete_if_exists(log_bmp_sys->out.name); } if (UNIV_LIKELY(success)) { @@ -544,7 +546,6 @@ log_online_start_bitmap_file(void) fprintf(stderr, "InnoDB: Error: Cannot create \'%s\'\n", log_bmp_sys->out.name); - log_bmp_sys->out.file = -1; return FALSE; } @@ -563,9 +564,9 @@ log_online_rotate_bitmap_file( ib_uint64_t next_file_start_lsn) /*!out.file != -1) { + if (log_bmp_sys->out.file != os_file_invalid) { os_file_close(log_bmp_sys->out.file); - log_bmp_sys->out.file = -1; + log_bmp_sys->out.file = os_file_invalid; } log_bmp_sys->out_seq_num++; log_online_make_bitmap_name(next_file_start_lsn); @@ -613,6 +614,7 @@ log_online_read_init(void) os_file_dir_t bitmap_dir; os_file_stat_t bitmap_dir_file_info; ib_uint64_t last_file_start_lsn = MIN_TRACKED_LSN; + size_t srv_data_home_len; /* Bitmap data start and end in a bitmap block must be 8-byte aligned. */ @@ -620,20 +622,39 @@ log_online_read_init(void) compile_time_assert(MODIFIED_PAGE_BLOCK_BITMAP_LEN % 8 == 0); log_bmp_sys = ut_malloc(sizeof(*log_bmp_sys)); + log_bmp_sys->read_buf_ptr = ut_malloc(FOLLOW_SCAN_SIZE + + OS_FILE_LOG_BLOCK_SIZE); + log_bmp_sys->read_buf = ut_align(log_bmp_sys->read_buf_ptr, + OS_FILE_LOG_BLOCK_SIZE); mutex_create(log_bmp_sys_mutex_key, &log_bmp_sys->mutex, SYNC_LOG_ONLINE); + /* Initialize bitmap file directory from srv_data_home and add a path + separator if needed. */ + srv_data_home_len = strlen(srv_data_home); + ut_a (srv_data_home_len < FN_REFLEN); + strcpy(log_bmp_sys->bmp_file_home, srv_data_home); + if (srv_data_home_len + && log_bmp_sys->bmp_file_home[srv_data_home_len - 1] + != SRV_PATH_SEPARATOR) { + + ut_a (srv_data_home_len < FN_REFLEN - 1); + log_bmp_sys->bmp_file_home[srv_data_home_len] + = SRV_PATH_SEPARATOR; + log_bmp_sys->bmp_file_home[srv_data_home_len + 1] = '\0'; + } + /* Enumerate existing bitmap files to either open the last one to get the last tracked LSN either to find that there are none and start tracking from scratch. */ log_bmp_sys->out.name[0] = '\0'; log_bmp_sys->out_seq_num = 0; - bitmap_dir = os_file_opendir(srv_data_home, TRUE); + bitmap_dir = os_file_opendir(log_bmp_sys->bmp_file_home, TRUE); ut_a(bitmap_dir); - while (!os_file_readdir_next_file(srv_data_home, bitmap_dir, - &bitmap_dir_file_info)) { + while (!os_file_readdir_next_file(log_bmp_sys->bmp_file_home, + bitmap_dir, &bitmap_dir_file_info)) { ulong file_seq_num; ib_uint64_t file_start_lsn; @@ -648,8 +669,8 @@ log_online_read_init(void) && bitmap_dir_file_info.size > 0) { log_bmp_sys->out_seq_num = file_seq_num; last_file_start_lsn = file_start_lsn; - /* No dir component (srv_data_home) here, because - that's the cwd */ + /* No dir component (log_bmp_sys->bmp_file_home) here, + because that's the cwd */ strncpy(log_bmp_sys->out.name, bitmap_dir_file_info.name, FN_REFLEN - 1); log_bmp_sys->out.name[FN_REFLEN - 1] = '\0'; @@ -659,7 +680,7 @@ log_online_read_init(void) if (os_file_closedir(bitmap_dir)) { os_file_get_last_error(TRUE); fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n", - srv_data_home); + log_bmp_sys->bmp_file_home); exit(1); } @@ -762,9 +783,9 @@ log_online_read_shutdown(void) { ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list; - if (log_bmp_sys->out.file != -1) { + if (log_bmp_sys->out.file != os_file_invalid) { os_file_close(log_bmp_sys->out.file); - log_bmp_sys->out.file = -1; + log_bmp_sys->out.file = os_file_invalid; } rbt_free(log_bmp_sys->modified_pages); @@ -777,6 +798,7 @@ log_online_read_shutdown(void) mutex_free(&log_bmp_sys->mutex); + ut_free(log_bmp_sys->read_buf_ptr); ut_free(log_bmp_sys); } @@ -978,8 +1000,8 @@ log_online_follow_log_seg( mutex_enter(&log_sys->mutex); log_group_read_log_seg(LOG_RECOVER, log_bmp_sys->read_buf, - group, block_start_lsn, block_end_lsn); - mutex_exit(&log_sys->mutex); + group, block_start_lsn, block_end_lsn, TRUE); + /* log_group_read_log_seg will release the log_sys->mutex for us */ while (log_block < log_block_end && log_bmp_sys->next_parse_lsn < log_bmp_sys->end_lsn) { @@ -1256,15 +1278,18 @@ log_online_setup_bitmap_file_range( os_file_dir_t bitmap_dir; os_file_stat_t bitmap_dir_file_info; ulong first_file_seq_num = ULONG_MAX; + ulong last_file_seq_num = 0; ib_uint64_t first_file_start_lsn = IB_ULONGLONG_MAX; + ut_ad(range_end >= range_start); + bitmap_files->count = 0; bitmap_files->files = NULL; /* 1st pass: size the info array */ bitmap_dir = os_file_opendir(srv_data_home, FALSE); - if (!bitmap_dir) { + if (UNIV_UNLIKELY(!bitmap_dir)) { fprintf(stderr, "InnoDB: Error: " "failed to open bitmap directory \'%s\'\n", @@ -1286,12 +1311,17 @@ log_online_setup_bitmap_file_range( continue; } + if (file_seq_num > last_file_seq_num) { + + last_file_seq_num = file_seq_num; + } + if (file_start_lsn >= range_start || file_start_lsn == first_file_start_lsn || first_file_start_lsn > range_start) { /* A file that falls into the range */ - bitmap_files->count++; + if (file_start_lsn < first_file_start_lsn) { first_file_start_lsn = file_start_lsn; @@ -1309,23 +1339,27 @@ log_online_setup_bitmap_file_range( } } - ut_a(first_file_seq_num != ULONG_MAX || bitmap_files->count == 0); + if (UNIV_UNLIKELY(os_file_closedir(bitmap_dir))) { - if (os_file_closedir(bitmap_dir)) { os_file_get_last_error(TRUE); fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n", srv_data_home); return FALSE; } - if (!bitmap_files->count) { + if (first_file_seq_num == ULONG_MAX && last_file_seq_num == 0) { + + bitmap_files->count = 0; return TRUE; } + bitmap_files->count = last_file_seq_num - first_file_seq_num + 1; + /* 2nd pass: get the file names in the file_seq_num order */ bitmap_dir = os_file_opendir(srv_data_home, FALSE); - if (!bitmap_dir) { + if (UNIV_UNLIKELY(!bitmap_dir)) { + fprintf(stderr, "InnoDB: Error: " "failed to open bitmap directory \'%s\'\n", srv_data_home); @@ -1349,11 +1383,25 @@ log_online_setup_bitmap_file_range( &file_start_lsn) || file_start_lsn >= range_end || file_start_lsn < first_file_start_lsn) { + continue; } array_pos = file_seq_num - first_file_seq_num; + if (UNIV_UNLIKELY(array_pos >= bitmap_files->count)) { + + fprintf(stderr, + "InnoDB: Error: inconsistent bitmap file " + "directory for a " + "INFORMATION_SCHEMA.INNODB_CHANGED_PAGES query" + "\n"); + free(bitmap_files->files); + return FALSE; + } + + if (file_seq_num > bitmap_files->files[array_pos].seq_num) { + bitmap_files->files[array_pos].seq_num = file_seq_num; strncpy(bitmap_files->files[array_pos].name, bitmap_dir_file_info.name, FN_REFLEN); @@ -1364,7 +1412,8 @@ log_online_setup_bitmap_file_range( } } - if (os_file_closedir(bitmap_dir)) { + if (UNIV_UNLIKELY(os_file_closedir(bitmap_dir))) { + os_file_get_last_error(TRUE); fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n", srv_data_home); @@ -1411,6 +1460,8 @@ log_online_open_bitmap_file_read_only( ulint size_low; ulint size_high; + ut_ad(name[0] != '\0'); + ut_snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name); bitmap_file->file = os_file_create_simple_no_error_handling(innodb_file_bmp_key, @@ -1418,7 +1469,8 @@ log_online_open_bitmap_file_read_only( OS_FILE_OPEN, OS_FILE_READ_ONLY, &success); - if (!success) { + if (UNIV_UNLIKELY(!success)) { + /* Here and below assume that bitmap file names do not contain apostrophes, thus no need for ut_print_filename(). */ fprintf(stderr, @@ -1461,7 +1513,8 @@ log_online_diagnose_bitmap_eof( || (bitmap_file->offset > bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) { - if (bitmap_file->offset != bitmap_file->size) { + if (UNIV_UNLIKELY(bitmap_file->offset != bitmap_file->size)) { + /* If we are not at EOF and we have less than one page to read, it's junk. This error is not fatal in itself. */ @@ -1472,7 +1525,8 @@ log_online_diagnose_bitmap_eof( bitmap_file->name); } - if (!last_page_in_run) { + if (UNIV_UNLIKELY(!last_page_in_run)) { + /* We are at EOF but the last read page did not finish a run */ /* It's a "Warning" here because it's not a fatal error @@ -1512,18 +1566,29 @@ log_online_bitmap_iterator_init( if (!log_online_setup_bitmap_file_range(&i->in_files, min_lsn, max_lsn)) { + i->failed = TRUE; return FALSE; } - ut_a(i->in_files.count > 0); + i->in_i = 0; + + if (i->in_files.count == 0) { + + /* Empty range */ + i->in.file = os_file_invalid; + i->page = NULL; + i->failed = FALSE; + return TRUE; + } /* Open the 1st bitmap file */ - i->in_i = 0; - if (!log_online_open_bitmap_file_read_only(i->in_files.files[i->in_i]. - name, - &i->in)) { + if (UNIV_UNLIKELY(!log_online_open_bitmap_file_read_only( + i->in_files.files[i->in_i].name, + &i->in))) { + i->in_i = i->in_files.count; free(i->in_files.files); + i->failed = TRUE; return FALSE; } @@ -1534,6 +1599,7 @@ log_online_bitmap_iterator_init( i->first_page_id = 0; i->last_page_in_run = TRUE; i->changed = FALSE; + i->failed = FALSE; return TRUE; } @@ -1548,11 +1614,20 @@ log_online_bitmap_iterator_release( { ut_a(i); - if (i->in_i < i->in_files.count) { + if (i->in.file != os_file_invalid) { + os_file_close(i->in.file); + i->in.file = os_file_invalid; } - ut_free(i->in_files.files); - ut_free(i->page); + if (i->in_files.files) { + + ut_free(i->in_files.files); + } + if (i->page) { + + ut_free(i->page); + } + i->failed = TRUE; } /*********************************************************************//** @@ -1567,10 +1642,16 @@ log_online_bitmap_iterator_next( log_bitmap_iterator_t *i) /*!bit_offset < MODIFIED_PAGE_BLOCK_BITMAP_LEN) + if (UNIV_UNLIKELY(i->in_files.count == 0)) { + + return FALSE; + } + + if (UNIV_LIKELY(i->bit_offset < MODIFIED_PAGE_BLOCK_BITMAP_LEN)) { ++i->bit_offset; i->changed = @@ -1587,29 +1668,56 @@ log_online_bitmap_iterator_next( /* Advance file */ i->in_i++; - os_file_close(i->in.file); - log_online_diagnose_bitmap_eof(&i->in, - i->last_page_in_run); - if (i->in_i == i->in_files.count - || i->in_files.files[i->in_i].seq_num == 0) { + success = os_file_close_no_error_handling(i->in.file); + i->in.file = os_file_invalid; + if (UNIV_UNLIKELY(!success)) { + + os_file_get_last_error(TRUE); + i->failed = TRUE; + return FALSE; + } + + success = log_online_diagnose_bitmap_eof( + &i->in, i->last_page_in_run); + if (UNIV_UNLIKELY(!success)) { + + i->failed = TRUE; + return FALSE; + + } + + if (i->in_i == i->in_files.count) { return FALSE; } - if (!log_online_open_bitmap_file_read_only( + if (UNIV_UNLIKELY(i->in_files.files[i->in_i].seq_num + == 0)) { + + i->failed = TRUE; + return FALSE; + } + + success = log_online_open_bitmap_file_read_only( i->in_files.files[i->in_i].name, - &i->in)) { + &i->in); + if (UNIV_UNLIKELY(!success)) { + + i->failed = TRUE; return FALSE; } } - if (!log_online_read_bitmap_page(&i->in, i->page, - &checksum_ok)) { + success = log_online_read_bitmap_page(&i->in, i->page, + &checksum_ok); + if (UNIV_UNLIKELY(!success)) { + os_file_get_last_error(TRUE); fprintf(stderr, "InnoDB: Warning: failed reading " "changed page bitmap file \'%s\'\n", i->in_files.files[i->in_i].name); + i->failed = TRUE; return FALSE; } } @@ -1666,7 +1774,7 @@ log_online_purge_changed_page_bitmaps( /* If we have to delete the current output file, close it first. */ os_file_close(log_bmp_sys->out.file); - log_bmp_sys->out.file = -1; + log_bmp_sys->out.file = os_file_invalid; } for (i = 0; i < bitmap_files.count; i++) { diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c index 4e179afd50c..9c26bd8eac6 100644 --- a/storage/xtradb/log/log0recv.c +++ b/storage/xtradb/log/log0recv.c @@ -553,7 +553,8 @@ recv_copy_group( } log_group_read_log_seg(LOG_RECOVER, log_sys->buf, - up_to_date_group, start_lsn, end_lsn); + up_to_date_group, start_lsn, end_lsn, + FALSE); len = (ulint) (end_lsn - start_lsn); @@ -597,7 +598,7 @@ recv_synchronize_groups( ut_a(start_lsn != end_lsn); log_group_read_log_seg(LOG_RECOVER, recv_sys->last_block, - up_to_date_group, start_lsn, end_lsn); + up_to_date_group, start_lsn, end_lsn, FALSE); group = UT_LIST_GET_FIRST(log_sys->log_groups); @@ -1716,19 +1717,6 @@ recv_recover_page_func( } #endif /* UNIV_ZIP_DEBUG */ - mutex_enter(&(recv_sys->mutex)); - - if (recv_max_page_lsn < page_lsn) { - recv_max_page_lsn = page_lsn; - } - - recv_addr->state = RECV_PROCESSED; - - ut_a(recv_sys->n_addrs); - recv_sys->n_addrs--; - - mutex_exit(&(recv_sys->mutex)); - #ifndef UNIV_HOTBACKUP if (modification_to_page) { ut_a(block); @@ -1745,6 +1733,20 @@ recv_recover_page_func( mtr.modifications = FALSE; mtr_commit(&mtr); + + mutex_enter(&(recv_sys->mutex)); + + if (recv_max_page_lsn < page_lsn) { + recv_max_page_lsn = page_lsn; + } + + recv_addr->state = RECV_PROCESSED; + + ut_a(recv_sys->n_addrs); + recv_sys->n_addrs--; + + mutex_exit(&(recv_sys->mutex)); + } #ifndef UNIV_HOTBACKUP @@ -2894,7 +2896,7 @@ recv_group_scan_log_recs( end_lsn = start_lsn + RECV_SCAN_SIZE; log_group_read_log_seg(LOG_RECOVER, log_sys->buf, - group, start_lsn, end_lsn); + group, start_lsn, end_lsn, FALSE); finished = recv_scan_log_recs( (buf_pool_get_n_pages() diff --git a/storage/xtradb/mem/mem0mem.c b/storage/xtradb/mem/mem0mem.c index 7727760f1cd..797de06c896 100644 --- a/storage/xtradb/mem/mem0mem.c +++ b/storage/xtradb/mem/mem0mem.c @@ -353,7 +353,13 @@ mem_heap_create_block( block = (mem_block_t*) buf_block->frame; } - ut_ad(block); + if(!block) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Unable to allocate memory of size %lu.\n", + len); + ut_error; + } block->buf_block = buf_block; block->free_block = NULL; #else /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/mtr/mtr0mtr.c b/storage/xtradb/mtr/mtr0mtr.c index 9eb7b18f301..083692efd77 100644 --- a/storage/xtradb/mtr/mtr0mtr.c +++ b/storage/xtradb/mtr/mtr0mtr.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -59,72 +59,81 @@ mtr_block_dirtied( /*****************************************************************//** Releases the item in the slot given. */ -static +static __attribute__((nonnull)) void -mtr_memo_slot_release( -/*==================*/ - mtr_t* mtr, /*!< in: mtr */ +mtr_memo_slot_release_func( +/*=======================*/ +#ifdef UNIV_DEBUG + mtr_t* mtr, /*!< in/out: mini-transaction */ +#endif /* UNIV_DEBUG */ mtr_memo_slot_t* slot) /*!< in: memo slot */ { - void* object; - ulint type; - - ut_ad(mtr); - ut_ad(slot); - -#ifndef UNIV_DEBUG - UT_NOT_USED(mtr); -#endif /* UNIV_DEBUG */ - - object = slot->object; - type = slot->type; - - if (UNIV_LIKELY(object != NULL)) { - if (type <= MTR_MEMO_BUF_FIX) { - buf_page_release((buf_block_t*)object, type); - } else if (type == MTR_MEMO_S_LOCK) { - rw_lock_s_unlock((rw_lock_t*)object); -#ifdef UNIV_DEBUG - } else if (type != MTR_MEMO_X_LOCK) { - ut_ad(type == MTR_MEMO_MODIFY); - ut_ad(mtr_memo_contains(mtr, object, - MTR_MEMO_PAGE_X_FIX)); -#endif /* UNIV_DEBUG */ - } else { - rw_lock_x_unlock((rw_lock_t*)object); - } - } - + void* object = slot->object; slot->object = NULL; + + /* slot release is a local operation for the current mtr. + We must not be holding the flush_order mutex while + doing this. */ + ut_ad(!log_flush_order_mutex_own()); + + switch (slot->type) { + case MTR_MEMO_PAGE_S_FIX: + case MTR_MEMO_PAGE_X_FIX: + case MTR_MEMO_BUF_FIX: + buf_page_release((buf_block_t*) object, slot->type); + break; + case MTR_MEMO_S_LOCK: + rw_lock_s_unlock((rw_lock_t*) object); + break; + case MTR_MEMO_X_LOCK: + rw_lock_x_unlock((rw_lock_t*) object); + break; +#ifdef UNIV_DEBUG + default: + ut_ad(slot->type == MTR_MEMO_MODIFY); + ut_ad(mtr_memo_contains(mtr, object, MTR_MEMO_PAGE_X_FIX)); +#endif /* UNIV_DEBUG */ + } } +#ifdef UNIV_DEBUG +# define mtr_memo_slot_release(mtr, slot) mtr_memo_slot_release_func(mtr, slot) +#else /* UNIV_DEBUG */ +# define mtr_memo_slot_release(mtr, slot) mtr_memo_slot_release_func(slot) +#endif /* UNIV_DEBUG */ + /**********************************************************//** Releases the mlocks and other objects stored in an mtr memo. They are released in the order opposite to which they were pushed to the memo. */ -static +static __attribute__((nonnull)) void mtr_memo_pop_all( /*=============*/ - mtr_t* mtr) /*!< in: mtr */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { - mtr_memo_slot_t* slot; - dyn_array_t* memo; - ulint offset; + const dyn_block_t* block; - ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in commit */ - memo = &(mtr->memo); - offset = dyn_array_get_data_size(memo); + for (block = dyn_array_get_last_block(&mtr->memo); + block; + block = dyn_array_get_prev_block(&mtr->memo, block)) { + const mtr_memo_slot_t* start + = (mtr_memo_slot_t*) dyn_block_get_data(block); + mtr_memo_slot_t* slot + = (mtr_memo_slot_t*) (dyn_block_get_data(block) + + dyn_block_get_used(block)); - while (offset > 0) { - offset -= sizeof(mtr_memo_slot_t); - slot = dyn_array_get_element(memo, offset); + ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t))); - mtr_memo_slot_release(mtr, slot); + while (slot-- != start) { + if (slot->object != NULL) { + mtr_memo_slot_release(mtr, slot); + } + } } } @@ -320,42 +329,36 @@ UNIV_INTERN void mtr_memo_release( /*=============*/ - mtr_t* mtr, /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction */ void* object, /*!< in: object */ ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ { - mtr_memo_slot_t* slot; - dyn_array_t* memo; - ulint offset; + const dyn_block_t* block; - ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); + /* We cannot release a page that has been written to in the + middle of a mini-transaction. */ + ut_ad(!mtr->modifications || type != MTR_MEMO_PAGE_X_FIX); - memo = &(mtr->memo); + for (block = dyn_array_get_last_block(&mtr->memo); + block; + block = dyn_array_get_prev_block(&mtr->memo, block)) { + const mtr_memo_slot_t* start + = (mtr_memo_slot_t*) dyn_block_get_data(block); + mtr_memo_slot_t* slot + = (mtr_memo_slot_t*) (dyn_block_get_data(block) + + dyn_block_get_used(block)); - offset = dyn_array_get_data_size(memo); + ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t))); - log_flush_order_mutex_enter(); - while (offset > 0) { - offset -= sizeof(mtr_memo_slot_t); - - slot = dyn_array_get_element(memo, offset); - - if (object == slot->object && type == slot->type) { - - /* We cannot release a page that has been written - to in the middle of a mini-transaction. */ - - ut_ad(!(mtr->modifications - && slot->type == MTR_MEMO_PAGE_X_FIX)); - - mtr_memo_slot_release(mtr, slot); - - break; + while (slot-- != start) { + if (object == slot->object && type == slot->type) { + mtr_memo_slot_release(mtr, slot); + return; + } } } - log_flush_order_mutex_exit(); } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index 8f7f8216782..ae6ba05c9f6 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -21,7 +21,7 @@ Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ***********************************************************************/ @@ -66,6 +66,13 @@ Created 10/21/1995 Heikki Tuuri #define IOCP_SHUTDOWN_KEY (ULONG_PTR)-1 #endif +#if defined(UNIV_LINUX) && defined(HAVE_SYS_IOCTL_H) +# include +# ifndef DFS_IOCTL_ATOMIC_WRITE_SET +# define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) +# endif +#endif + /* This specifies the file permissions InnoDB uses when it creates files in Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to my_umask */ @@ -1455,40 +1462,37 @@ os_file_set_nocache( } -#ifdef __linux__ -#include -#ifndef DFS_IOCTL_ATOMIC_WRITE_SET -#define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) -#endif -static int os_file_set_atomic_writes(os_file_t file, const char *name) +/****************************************************************//** +Tries to enable the atomic write feature, if available, for the specified file +handle. +@return TRUE if success */ +static __attribute__((warn_unused_result)) +ibool +os_file_set_atomic_writes( +/*======================*/ + const char* name /*!< in: name of the file */ + __attribute__((unused)), + os_file_t file /*!< in: handle to the file */ + __attribute__((unused))) + { - int atomic_option = 1; +#ifdef DFS_IOCTL_ATOMIC_WRITE_SET + int atomic_option = 1; - int ret = ioctl (file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option); + if (ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option)) { - if (ret) { - fprintf(stderr, - "InnoDB : can't use atomic write on %s, errno %d\n", - name, errno); - return ret; + os_file_handle_error_no_exit(name, "ioctl"); + return(FALSE); } - return ret; -} -#else -static int os_file_set_atomic_writes(os_file_t file, const char *name) -{ - fprintf(stderr, - "InnoDB : can't use atomic writes on %s - not implemented on this platform." - "innodb_use_atomic_writes needs to be 0.\n", - name); -#ifdef _WIN32 - SetLastError(ERROR_INVALID_FUNCTION); + + return(TRUE); #else - errno = EINVAL; + fprintf(stderr, "InnoDB: Error: trying to enable atomic writes on " + "non-supported platform! Please restart with " + "innodb_use_atomic_writes disabled.\n"); + return(FALSE); #endif - return -1; } -#endif /****************************************************************//** NOTE! Use the corresponding macro os_file_create(), not directly @@ -1780,11 +1784,13 @@ try_again: file = -1; } #endif /* USE_FILE_LOCK */ - if (srv_use_atomic_writes && type == OS_DATA_FILE - && os_file_set_atomic_writes(file, name)) { - close(file); - *success = FALSE; - file = -1; + + if (srv_use_atomic_writes && type == OS_DATA_FILE + && os_file_set_atomic_writes(name, file)) { + + *success = FALSE; + close(file); + file = -1; } return(file); @@ -1996,7 +2002,6 @@ os_file_close_func( #endif } -#ifdef UNIV_HOTBACKUP /***********************************************************************//** Closes a file handle. @return TRUE if success */ @@ -2031,7 +2036,6 @@ os_file_close_no_error_handling( return(TRUE); #endif } -#endif /* UNIV_HOTBACKUP */ /***********************************************************************//** Gets a file size. @@ -2131,24 +2135,18 @@ os_file_set_size( desired_size = (ib_int64_t)size + (((ib_int64_t)size_high) << 32); #ifdef HAVE_POSIX_FALLOCATE - if (srv_use_posix_fallocate) { - if (posix_fallocate(file, current_size, desired_size) == -1) { - fprintf(stderr, - "InnoDB: Error: preallocating data for" - " file %s failed at\n" - "InnoDB: offset 0 size %lld %lld. Operating system" - " error number %d.\n" - "InnoDB: Check that the disk is not full" - " or a disk quota exceeded.\n" - "InnoDB: Some operating system error numbers" - " are described at\n" - "InnoDB: " - REFMAN "operating-system-error-codes.html\n", - name, (long long)size_high, (long long)size, errno); + if (srv_use_posix_fallocate) { - return (FALSE); + if (posix_fallocate(file, current_size, desired_size) == -1) { + + fprintf(stderr, "InnoDB: Error: preallocating file " + "space for file \'%s\' failed. Current size " + "%lld, desired size %lld\n", + name, current_size, desired_size); + os_file_handle_error_no_exit(name, "posix_fallocate"); + return(FALSE); } - return (TRUE); + return(TRUE); } #endif diff --git a/storage/xtradb/page/page0zip.c b/storage/xtradb/page/page0zip.c index 5357479908f..1cf707d0999 100644 --- a/storage/xtradb/page/page0zip.c +++ b/storage/xtradb/page/page0zip.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -837,11 +837,12 @@ page_zip_compress_node_ptrs( c_stream->next_in = (byte*) rec; c_stream->avail_in = rec_offs_data_size(offsets) - REC_NODE_PTR_SIZE; - ut_ad(c_stream->avail_in); - err = deflate(c_stream, Z_NO_FLUSH); - if (UNIV_UNLIKELY(err != Z_OK)) { - break; + if (c_stream->avail_in) { + err = deflate(c_stream, Z_NO_FLUSH); + if (UNIV_UNLIKELY(err != Z_OK)) { + break; + } } ut_ad(!c_stream->avail_in); @@ -2274,13 +2275,12 @@ zlib_done: if (UNIV_UNLIKELY (page_zip_get_trailer_len(page_zip, - dict_index_is_clust(index), NULL) + dict_index_is_clust(index)) + page_zip->m_end >= page_zip_get_size(page_zip))) { page_zip_fail(("page_zip_decompress_node_ptrs:" " %lu + %lu >= %lu, %lu\n", (ulong) page_zip_get_trailer_len( - page_zip, dict_index_is_clust(index), - NULL), + page_zip, dict_index_is_clust(index)), (ulong) page_zip->m_end, (ulong) page_zip_get_size(page_zip), (ulong) dict_index_is_clust(index))); @@ -2431,12 +2431,12 @@ zlib_done: page_zip->m_nonempty = mod_log_ptr != d_stream->next_in; } - if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, FALSE, NULL) + if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, FALSE) + page_zip->m_end >= page_zip_get_size(page_zip))) { page_zip_fail(("page_zip_decompress_sec: %lu + %lu >= %lu\n", (ulong) page_zip_get_trailer_len( - page_zip, FALSE, NULL), + page_zip, FALSE), (ulong) page_zip->m_end, (ulong) page_zip_get_size(page_zip))); return(FALSE); @@ -2762,12 +2762,12 @@ zlib_done: page_zip->m_nonempty = mod_log_ptr != d_stream->next_in; } - if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, TRUE, NULL) + if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, TRUE) + page_zip->m_end >= page_zip_get_size(page_zip))) { page_zip_fail(("page_zip_decompress_clust: %lu + %lu >= %lu\n", (ulong) page_zip_get_trailer_len( - page_zip, TRUE, NULL), + page_zip, TRUE), (ulong) page_zip->m_end, (ulong) page_zip_get_size(page_zip))); return(FALSE); @@ -4642,8 +4642,7 @@ page_zip_copy_recs( memcpy(page_zip, src_zip, sizeof *page_zip); page_zip->data = data; } - ut_ad(page_zip_get_trailer_len(page_zip, - dict_index_is_clust(index), NULL) + ut_ad(page_zip_get_trailer_len(page_zip, dict_index_is_clust(index)) + page_zip->m_end < page_zip_get_size(page_zip)); if (!page_is_leaf(src) diff --git a/storage/xtradb/read/read0read.c b/storage/xtradb/read/read0read.c index c04dae51ff5..3380d1bb4ba 100644 --- a/storage/xtradb/read/read0read.c +++ b/storage/xtradb/read/read0read.c @@ -150,6 +150,7 @@ read_view_create_low( { if (view == NULL) { view = ut_malloc(sizeof(read_view_t)); + srv_read_views_memory += sizeof(read_view_t); view->max_descr = 0; view->descriptors = NULL; } @@ -159,6 +160,8 @@ read_view_create_low( /* avoid frequent re-allocations by extending the array to the desired size + 10% */ + srv_read_views_memory += (n + n / 10 - view->max_descr) * + sizeof(trx_id_t); view->max_descr = n + n / 10; view->descriptors = ut_realloc(view->descriptors, view->max_descr * @@ -370,6 +373,9 @@ read_view_free( { ut_ad(mutex_own(&kernel_mutex)); + srv_read_views_memory -= sizeof(read_view_t) + + view->max_descr * sizeof(trx_id_t); + if (view->descriptors != NULL) { ut_free(view->descriptors); } diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index 0002f4410d6..ee2938e4865 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1710,6 +1710,7 @@ row_ins_scan_sec_index_for_duplicate( do { const rec_t* rec = btr_pcur_get_rec(&pcur); const buf_block_t* block = btr_pcur_get_block(&pcur); + ulint lock_type; if (page_rec_is_infimum(rec)) { @@ -1719,6 +1720,16 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + /* If the transaction isolation level is no stronger than + READ COMMITTED, then avoid gap locks. */ + if (!page_rec_is_supremum(rec) + && thr_get_trx(thr)->isolation_level + <= TRX_ISO_READ_COMMITTED) { + lock_type = LOCK_REC_NOT_GAP; + } else { + lock_type = LOCK_ORDINARY; + } + if (allow_duplicates) { /* If the SQL-query will update or replace @@ -1727,13 +1738,11 @@ row_ins_scan_sec_index_for_duplicate( INSERT ON DUPLICATE KEY UPDATE). */ err = row_ins_set_exclusive_rec_lock( - LOCK_ORDINARY, block, - rec, index, offsets, thr); + lock_type, block, rec, index, offsets, thr); } else { err = row_ins_set_shared_rec_lock( - LOCK_ORDINARY, block, - rec, index, offsets, thr); + lock_type, block, rec, index, offsets, thr); } switch (err) { diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c index 3a18cfc679e..3e8a17db91b 100644 --- a/storage/xtradb/row/row0mysql.c +++ b/storage/xtradb/row/row0mysql.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -55,6 +55,7 @@ Created 9/17/2000 Heikki Tuuri #include "ha_prototypes.h" #include "m_string.h" #include "my_sys.h" +#include "ha_prototypes.h" /** Provide optional 4.x backwards compatibility for 5.0 and above */ UNIV_INTERN ibool row_rollback_on_timeout = FALSE; @@ -966,17 +967,13 @@ row_update_statistics_if_needed( if (!srv_stats_auto_update) return; - /* Calculate new statistics if 1 / 16 of table has been modified - since the last time a statistics batch was run, or if - stat_modified_counter > 2 000 000 000 (to avoid wrap-around). - We calculate statistics at most every 16th round, since we may have - a counter table which is very small and updated very often. */ + if (DICT_TABLE_CHANGED_TOO_MUCH(table)) { - if (counter > 2000000000 - || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) { - - dict_update_statistics(table, FALSE /* update even if stats - are initialized */, TRUE); + dict_update_statistics( + table, + FALSE, /* update even if stats are initialized */ + TRUE, + TRUE /* only update if stats changed too much */); } } @@ -3181,8 +3178,11 @@ next_rec: dict_table_autoinc_lock(table); dict_table_autoinc_initialize(table, 1); dict_table_autoinc_unlock(table); - dict_update_statistics(table, FALSE /* update even if stats are - initialized */, TRUE); + dict_update_statistics( + table, + FALSE, /* update even if stats are initialized */ + TRUE, + FALSE /* update even if not changed too much */); trx_commit_for_mysql(trx); @@ -3973,6 +3973,7 @@ row_rename_table_for_mysql( ut_a(old_name != NULL); ut_a(new_name != NULL); + ut_ad(trx->state == TRX_ACTIVE); if (srv_created_new_raw || srv_force_recovery) { fputs("InnoDB: A new raw disk partition was initialized or\n" @@ -3997,7 +3998,6 @@ row_rename_table_for_mysql( } trx->op_info = "renaming table"; - trx_start_if_not_started(trx); old_is_tmp = row_is_mysql_tmp_table_name(old_name); new_is_tmp = row_is_mysql_tmp_table_name(new_name); @@ -4092,12 +4092,29 @@ row_rename_table_for_mysql( goto end; } else if (!new_is_tmp) { /* Rename all constraints. */ + char new_table_name[MAX_TABLE_NAME_LEN] = ""; + uint errors = 0; info = pars_info_create(); pars_info_add_str_literal(info, "new_table_name", new_name); pars_info_add_str_literal(info, "old_table_name", old_name); + strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN); + innobase_convert_to_system_charset( + strchr(new_table_name, '/') + 1, + strchr(new_name, '/') +1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + /* Table name could not be converted from charset + my_charset_filename to UTF-8. This means that the + table name is already in UTF-8 (#mysql#50). */ + strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN); + } + + pars_info_add_str_literal(info, "new_table_utf8", new_table_name); + err = que_eval_sql( info, "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n" @@ -4109,6 +4126,7 @@ row_rename_table_for_mysql( "old_t_name_len INT;\n" "new_db_name_len INT;\n" "id_len INT;\n" + "offset INT;\n" "found INT;\n" "BEGIN\n" "found := 1;\n" @@ -4117,8 +4135,6 @@ row_rename_table_for_mysql( "new_db_name := SUBSTR(:new_table_name, 0,\n" " new_db_name_len);\n" "old_t_name_len := LENGTH(:old_table_name);\n" - "gen_constr_prefix := CONCAT(:old_table_name,\n" - " '_ibfk_');\n" "WHILE found = 1 LOOP\n" " SELECT ID INTO foreign_id\n" " FROM SYS_FOREIGN\n" @@ -4135,12 +4151,13 @@ row_rename_table_for_mysql( " id_len := LENGTH(foreign_id);\n" " IF (INSTR(foreign_id, '/') > 0) THEN\n" " IF (INSTR(foreign_id,\n" - " gen_constr_prefix) > 0)\n" + " '_ibfk_') > 0)\n" " THEN\n" + " offset := INSTR(foreign_id, '_ibfk_') - 1;\n" " new_foreign_id :=\n" - " CONCAT(:new_table_name,\n" - " SUBSTR(foreign_id, old_t_name_len,\n" - " id_len - old_t_name_len));\n" + " CONCAT(:new_table_utf8,\n" + " SUBSTR(foreign_id, offset,\n" + " id_len - offset));\n" " ELSE\n" " new_foreign_id :=\n" " CONCAT(new_db_name,\n" diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index dec192585ce..0907b7f823f 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -57,6 +57,8 @@ Created 12/19/1997 Heikki Tuuri #include "read0read.h" #include "buf0lru.h" #include "ha_prototypes.h" +#include "m_string.h" /* for my_sys.h */ +#include "my_sys.h" /* DEBUG_SYNC_C */ #include "my_compare.h" /* enum icp_result */ @@ -4127,7 +4129,9 @@ wait_table_again: } rec_loop: + DEBUG_SYNC_C("row_search_rec_loop"); if (trx_is_interrupted(trx)) { + btr_pcur_store_position(pcur, &mtr); err = DB_INTERRUPTED; goto normal_return; } @@ -5095,8 +5099,8 @@ row_search_check_if_query_cache_permitted( trx->read_view = read_view_open_now(trx->id, - NULL, TRUE); - + trx->prebuilt_view, TRUE); + trx->prebuilt_view = trx->read_view; trx->global_read_view = trx->read_view; } } diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 3119c870d2c..ee8cc5a855b 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -317,7 +317,7 @@ UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS; /* Internal setting for "innodb_stats_method". Decides how InnoDB treats NULL value when collecting statistics. By default, it is set to SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */ -ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; +UNIV_INTERN ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; /** Time in seconds between automatic buffer pool dumps */ UNIV_INTERN uint srv_auto_lru_dump = 0; @@ -409,10 +409,11 @@ UNIV_INTERN ulong srv_sys_stats_root_page = 0; #endif UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE; -UNIV_INTERN ibool srv_use_atomic_writes = FALSE; +UNIV_INTERN ibool srv_use_atomic_writes = FALSE; #ifdef HAVE_POSIX_FALLOCATE -UNIV_INTERN ibool srv_use_posix_fallocate = TRUE; +UNIV_INTERN ibool srv_use_posix_fallocate = FALSE; #endif + UNIV_INTERN ibool srv_use_checksums = TRUE; UNIV_INTERN ibool srv_fast_checksum = FALSE; @@ -467,6 +468,9 @@ UNIV_INTERN ulint srv_n_rows_updated CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_rows_deleted CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_rows_read CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_read_views_memory CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_descriptors_memory CACHE_ALIGNED = 0; + UNIV_INTERN ulint srv_n_lock_deadlock_count CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_lock_wait_count CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_lock_wait_current_count CACHE_ALIGNED = 0; @@ -1925,7 +1929,8 @@ srv_suspend_mysql_thread( finish_time = (ib_int64_t) sec * 1000000 + ms; } - diff_time = (ulint) (finish_time - start_time); + diff_time = (finish_time > start_time) ? + (ulint) (finish_time - start_time) : 0; srv_n_lock_wait_current_count--; srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time; @@ -2136,6 +2141,9 @@ srv_printf_innodb_monitor( "; in additional pool allocated " ULINTPF "\n", ut_total_allocated_memory, mem_pool_get_reserved(mem_comm_pool)); + fprintf(file, + "Total memory allocated by read views " ULINTPF "\n", + srv_read_views_memory); /* Calcurate reserved memories */ if (btr_search_sys && btr_search_sys->hash_index[0]->heap) { btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap); @@ -2222,6 +2230,12 @@ srv_printf_innodb_monitor( fprintf(file, "%lu read views open inside InnoDB\n", UT_LIST_GET_LEN(trx_sys->view_list)); + fprintf(file, "%lu transactions active inside InnoDB\n", + UT_LIST_GET_LEN(trx_sys->trx_list)); + + fprintf(file, "%lu out of %lu descriptors used\n", + trx_sys->descr_n_used, trx_sys->descr_n_max); + if (UT_LIST_GET_LEN(trx_sys->view_list)) { read_view_t* view = UT_LIST_GET_LAST(trx_sys->view_list); @@ -2531,21 +2545,35 @@ srv_export_innodb_status(void) export_vars.innodb_rows_updated = srv_n_rows_updated; export_vars.innodb_rows_deleted = srv_n_rows_deleted; export_vars.innodb_truncated_status_writes = srv_truncated_status_writes; + export_vars.innodb_read_views_memory = srv_read_views_memory; + export_vars.innodb_descriptors_memory = srv_descriptors_memory; #ifdef UNIV_DEBUG - if (trx_sys->max_trx_id < purge_sys->done_trx_no) { - export_vars.innodb_purge_trx_id_age = 0; - } else { - export_vars.innodb_purge_trx_id_age = - trx_sys->max_trx_id - purge_sys->done_trx_no; - } + { + trx_id_t done_trx_no; + trx_id_t up_limit_id; - if (!purge_sys->view - || trx_sys->max_trx_id < purge_sys->view->up_limit_id) { - export_vars.innodb_purge_view_trx_id_age = 0; - } else { - export_vars.innodb_purge_view_trx_id_age = - trx_sys->max_trx_id - purge_sys->view->up_limit_id; + rw_lock_s_lock(&purge_sys->latch); + done_trx_no = purge_sys->done_trx_no; + up_limit_id = purge_sys->view + ? purge_sys->view->up_limit_id + : 0; + rw_lock_s_unlock(&purge_sys->latch); + + if (trx_sys->max_trx_id < done_trx_no) { + export_vars.innodb_purge_trx_id_age = 0; + } else { + export_vars.innodb_purge_trx_id_age = + trx_sys->max_trx_id - done_trx_no; + } + + if (!up_limit_id + || trx_sys->max_trx_id < up_limit_id) { + export_vars.innodb_purge_view_trx_id_age = 0; + } else { + export_vars.innodb_purge_view_trx_id_age = + trx_sys->max_trx_id - up_limit_id; + } } #endif /* UNIV_DEBUG */ diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c index 9e0477253cd..93416088f17 100644 --- a/storage/xtradb/srv/srv0start.c +++ b/storage/xtradb/srv/srv0start.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. @@ -496,12 +496,6 @@ io_handler_thread( } #endif /* !UNIV_HOTBACKUP */ -#ifdef __WIN__ -#define SRV_PATH_SEPARATOR '\\' -#else -#define SRV_PATH_SEPARATOR '/' -#endif - /*********************************************************************//** Normalizes a directory path for Windows: converts slashes to backslashes. */ UNIV_INTERN @@ -823,6 +817,7 @@ open_or_create_data_files( } if (ret == FALSE) { + const char* check_msg; /* We open the data file */ if (one_created) { @@ -920,13 +915,20 @@ open_or_create_data_files( return(DB_ERROR); } skip_size_check: - fil_read_first_page( + check_msg = fil_read_first_page( files[i], one_opened, &flags, #ifdef UNIV_LOG_ARCHIVE min_arch_log_no, max_arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ min_flushed_lsn, max_flushed_lsn); + if (check_msg) { + fprintf(stderr, + "InnoDB: Error: %s in data file %s\n", + check_msg, name); + return(DB_ERROR); + } + if (!one_opened && UNIV_PAGE_SIZE != fsp_flags_get_page_size(flags)) { @@ -1047,6 +1049,9 @@ skip_size_check: } if (ret == FALSE) { + + const char* check_msg; + /* We open the data file */ files[i] = os_file_create(innodb_file_data_key, @@ -1083,12 +1088,20 @@ skip_size_check: (ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9); } - fil_read_first_page( + check_msg = fil_read_first_page( files[i], one_opened, &flags, #ifdef UNIV_LOG_ARCHIVE min_arch_log_no, max_arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ min_flushed_lsn, max_flushed_lsn); + + if (check_msg) { + fprintf(stderr, + "InnoDB: Error: %s in doublewrite " + "buffer file %s\n", check_msg, name); + return(DB_ERROR); + } + one_opened = TRUE; } else { /* We created the data file and now write it full of diff --git a/storage/xtradb/sync/sync0arr.c b/storage/xtradb/sync/sync0arr.c index 5f293ad6a55..b5748f1b7d1 100644 --- a/storage/xtradb/sync/sync0arr.c +++ b/storage/xtradb/sync/sync0arr.c @@ -602,10 +602,6 @@ sync_array_deadlock_step( new = sync_array_find_thread(arr, thread); if (UNIV_UNLIKELY(new == start)) { - /* Stop running of other threads */ - - ut_dbg_stop_threads = TRUE; - /* Deadlock */ fputs("########################################\n" "DEADLOCK of threads detected!\n", stderr); @@ -943,6 +939,8 @@ sync_array_print_long_waits( # define SYNC_ARRAY_TIMEOUT 240 #endif + sync_array_enter(sync_primary_wait_array); + for (i = 0; i < sync_primary_wait_array->n_cells; i++) { double diff; @@ -977,6 +975,8 @@ sync_array_print_long_waits( } } + sync_array_exit(sync_primary_wait_array); + if (noticed) { fprintf(stderr, "InnoDB: ###### Starts InnoDB Monitor" diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index 2c44cee60fe..a56e55c0e19 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -140,7 +140,7 @@ UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key; #ifndef UNIV_HOTBACKUP #ifdef UNIV_DEBUG /* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */ -uint trx_rseg_n_slots_debug = 0; +UNIV_INTERN uint trx_rseg_n_slots_debug = 0; #endif /** This is used to track the maximum file format id known to InnoDB. It's @@ -726,7 +726,8 @@ trx_sys_doublewrite_init_or_restore_pages( /* Check if the page is corrupt */ if (UNIV_UNLIKELY - (buf_page_is_corrupted(read_buf, zip_size))) { + (buf_page_is_corrupted( + TRUE, read_buf, zip_size))) { fprintf(stderr, "InnoDB: Warning: database page" @@ -737,7 +738,8 @@ trx_sys_doublewrite_init_or_restore_pages( " the doublewrite buffer.\n", (ulong) space_id, (ulong) page_no); - if (buf_page_is_corrupted(page, zip_size)) { + if (buf_page_is_corrupted( + TRUE, page, zip_size)) { fprintf(stderr, "InnoDB: Dump of the page:\n"); buf_page_print( @@ -1324,6 +1326,8 @@ trx_sys_init_at_db_start(void) TRX_DESCR_ARRAY_INITIAL_SIZE); trx_sys->descr_n_max = TRX_DESCR_ARRAY_INITIAL_SIZE; trx_sys->descr_n_used = 0; + srv_descriptors_memory = TRX_DESCR_ARRAY_INITIAL_SIZE * + sizeof(trx_id_t); sys_header = trx_sysf_get(&mtr); diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index e70bc5ff0d1..8b7748b6c2f 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -135,6 +135,7 @@ trx_reserve_descriptor( n_max * sizeof(trx_id_t)); trx_sys->descr_n_max = n_max; + srv_descriptors_memory = n_max * sizeof(trx_id_t); } descr = trx_sys->descriptors + n_used - 1; @@ -219,7 +220,7 @@ trx_create( ut_ad(mutex_own(&kernel_mutex)); ut_ad(sess); - trx = mem_alloc(sizeof(trx_t)); + trx = ut_malloc(sizeof(trx_t)); trx->magic_n = TRX_MAGIC_N; @@ -487,7 +488,7 @@ trx_free( trx_release_descriptor(trx); - mem_free(trx); + ut_free(trx); } /********************************************************************//** @@ -545,7 +546,7 @@ trx_free_prepared( ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list)); - mem_free(trx); + ut_free(trx); } /********************************************************************//** @@ -1091,6 +1092,18 @@ trx_write_serialisation_history( trx->mysql_master_log_pos, TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr); + trx_sys_update_mysql_binlog_offset( + sys_header, + trx->mysql_relay_log_file_name, + trx->mysql_relay_log_pos, + TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr); + + trx_sys_update_mysql_binlog_offset( + sys_header, + trx->mysql_master_log_file_name, + trx->mysql_master_log_pos, + TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr); + trx->mysql_master_log_file_name = ""; } diff --git a/storage/xtradb/ut/ut0dbg.c b/storage/xtradb/ut/ut0dbg.c index 53ed4a53044..a440b72d32a 100644 --- a/storage/xtradb/ut/ut0dbg.c +++ b/storage/xtradb/ut/ut0dbg.c @@ -35,16 +35,6 @@ Created 1/30/1994 Heikki Tuuri UNIV_INTERN ulint ut_dbg_zero = 0; #endif -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) -/** If this is set to TRUE by ut_dbg_assertion_failed(), all threads -will stop at the next ut_a() or ut_ad(). */ -UNIV_INTERN ibool ut_dbg_stop_threads = FALSE; -#endif -#ifndef UT_DBG_USE_ABORT -/** A null pointer that will be dereferenced to trigger a memory trap */ -UNIV_INTERN ulint* ut_dbg_null_ptr = NULL; -#endif - /*************************************************************//** Report a failed assertion. */ UNIV_INTERN @@ -80,30 +70,8 @@ ut_dbg_assertion_failed( "InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: " REFMAN "forcing-innodb-recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) - ut_dbg_stop_threads = TRUE; -#endif } -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) -/*************************************************************//** -Stop a thread after assertion failure. */ -UNIV_INTERN -void -ut_dbg_stop_thread( -/*===============*/ - const char* file, - ulint line) -{ -#ifndef UNIV_HOTBACKUP - fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n", - os_thread_pf(os_thread_get_curr_id()), - innobase_basename(file), line); - os_thread_sleep(1000000000); -#endif /* !UNIV_HOTBACKUP */ -} -#endif - #ifdef UNIV_COMPILE_TEST_FUNCS #include diff --git a/storage/xtradb/ut/ut0ut.c b/storage/xtradb/ut/ut0ut.c index 31c8351a518..08ced5f56ef 100644 --- a/storage/xtradb/ut/ut0ut.c +++ b/storage/xtradb/ut/ut0ut.c @@ -730,6 +730,8 @@ ut_strerr( return("Operation was interrupted by end user"); case DB_TABLE_IN_FK_CHECK: return("Table is being used in foreign key check"); + case DB_IDENTIFIER_TOO_LONG: + return("Identifier name is too long"); /* do not add default: in order to produce a warning if new code is added to the enum but not added here */ }