summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/buf/buf0buf.c12
-rw-r--r--storage/innobase/dict/dict0crea.c59
-rw-r--r--storage/innobase/dict/dict0dict.c124
-rw-r--r--storage/innobase/dict/dict0load.c8
-rw-r--r--storage/innobase/fil/fil0fil.c102
-rw-r--r--storage/innobase/handler/ha_innodb.cc109
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c16
-rw-r--r--storage/innobase/include/buf0buf.h7
-rw-r--r--storage/innobase/include/dict0dict.h20
-rw-r--r--storage/innobase/include/dict0mem.h12
-rw-r--r--storage/innobase/include/dict0types.h5
-rw-r--r--storage/innobase/include/fil0fil.h13
-rw-r--r--storage/innobase/include/ha_prototypes.h22
-rw-r--r--storage/innobase/include/os0file.h2
-rw-r--r--storage/innobase/include/page0zip.ic20
-rw-r--r--storage/innobase/lock/lock0lock.c4
-rw-r--r--storage/innobase/log/log0recv.c27
-rw-r--r--storage/innobase/mem/mem0mem.c8
-rw-r--r--storage/innobase/os/os0file.c2
-rw-r--r--storage/innobase/page/page0zip.c16
-rw-r--r--storage/innobase/row/row0ins.c19
-rw-r--r--storage/innobase/row/row0mysql.c54
-rw-r--r--storage/innobase/srv/srv0srv.c3
-rw-r--r--storage/innobase/srv/srv0start.c12
-rw-r--r--storage/innobase/trx/trx0sys.c8
25 files changed, 510 insertions, 174 deletions
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 31be914afa0..5a8ddacac1a 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -520,6 +520,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 */
@@ -539,7 +541,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(&current_lsn)
@@ -1834,7 +1836,7 @@ lookup:
buf_read_page(space, zip_size, offset);
#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 */
}
@@ -2347,7 +2349,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;
}
@@ -3432,7 +3434,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),
@@ -3575,7 +3577,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/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index cb3dbcbe4ac..bd4e449d11b 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/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
@@ -44,6 +44,21 @@ Created 1/8/1996 Heikki Tuuri
#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
in the SYS_TABLES system table.
@@ -1424,26 +1439,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) {
- char* stripped_name;
/* 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)++);
- foreign->id = id;
- stripped_name = strchr(foreign->id, '/') + 1;
- if (innobase_check_identifier_length(stripped_name)) {
- fprintf(stderr, "InnoDB: Generated foreign key "
- "name (%s) is too long\n", foreign->id);
- return(DB_IDENTIFIER_TOO_LONG);
+ 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/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index a887ff0b1ca..aec2264ad1c 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -770,8 +770,10 @@ 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 */);
+ dict_update_statistics(
+ table,
+ TRUE, /* only update stats if not initialized */
+ FALSE /* update even if not changed too much */);
}
return(table);
@@ -1114,22 +1116,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;
+
+ /* 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);
+ }
+ }
- /* This is a >= 4.0.18 format id */
+ 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,
@@ -1137,11 +1195,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 */
@@ -4340,10 +4423,14 @@ 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 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;
@@ -4373,7 +4460,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;
}
@@ -4532,7 +4622,10 @@ dict_table_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
- dict_update_statistics(table, FALSE /* update even if initialized */);
+ dict_update_statistics(
+ table,
+ FALSE, /* update even if initialized */
+ FALSE /* update even if not changed too much */);
dict_table_stats_lock(table, RW_S_LATCH);
@@ -4679,7 +4772,6 @@ dict_print_info_on_foreign_key_in_create_format(
dict_foreign_t* foreign, /*!< in: foreign key constraint */
ibool add_newline) /*!< in: whether to add a newline */
{
- char constraint_name[MAX_TABLE_NAME_LEN];
const char* stripped_id;
ulint i;
@@ -4701,9 +4793,7 @@ dict_print_info_on_foreign_key_in_create_format(
}
fputs(" CONSTRAINT ", file);
- innobase_convert_from_id(&my_charset_filename, constraint_name,
- stripped_id, MAX_TABLE_NAME_LEN);
- ut_print_name(file, trx, FALSE, constraint_name);
+ ut_print_name(file, trx, FALSE, stripped_id);
fputs(" FOREIGN KEY (", file);
for (i = 0;;) {
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index 208d013e82d..f6e7a417f88 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/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
@@ -352,8 +352,10 @@ dict_process_sys_tables_rec(
/* Update statistics if DICT_TABLE_UPDATE_STATS
is set */
- dict_update_statistics(*table, FALSE /* update even if
- initialized */);
+ dict_update_statistics(
+ *table,
+ FALSE, /* update even if initialized */
+ FALSE /* update even if not changed too much */);
}
return(NULL);
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index c3a206fb009..3e10d45b3a4 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/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
@@ -1860,10 +1860,62 @@ fil_write_flushed_lsn_to_data_files(
}
/*******************************************************************//**
+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 */
@@ -1885,6 +1937,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 */
@@ -1892,13 +1945,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;
@@ -1906,7 +1964,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) {
@@ -1923,6 +1981,8 @@ fil_read_first_page(
*max_arch_log_no = arch_log_no;
}
#endif /* UNIV_LOG_ARCHIVE */
+
+ return(NULL);
}
/*================ SINGLE-TABLE TABLESPACES ==========================*/
@@ -3151,6 +3211,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;
@@ -3211,6 +3272,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);
@@ -3218,8 +3281,20 @@ fil_open_single_table_tablespace(
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 ",
@@ -3447,10 +3522,21 @@ fil_load_single_table_tablespace(
page = ut_align(buf2, UNIV_PAGE_SIZE);
if (size >= FIL_IBD_FILE_INITIAL_SIZE * 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 {
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 0bedbcca73c..3545d5b53bb 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1162,33 +1162,27 @@ innobase_convert_from_table_id(
/**********************************************************************
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. */
-extern "C" UNIV_INTERN
+extern "C"
my_bool
innobase_check_identifier_length(
/*=============================*/
- const char* id) /* in: identifier to check. it must belong
- to charset my_charset_filename */
+ const char* id) /* in: FK identifier to check excluding the
+ database portion. */
{
- char tmp[MAX_TABLE_NAME_LEN + 10];
- uint errors;
- uint len;
int well_formed_error = 0;
- CHARSET_INFO* cs1 = &my_charset_filename;
- CHARSET_INFO* cs2 = thd_charset(current_thd);
+ CHARSET_INFO *cs = system_charset_info;
+ DBUG_ENTER("innobase_check_identifier_length");
- len = strconvert(cs1, id, cs2, tmp, MAX_TABLE_NAME_LEN + 10, &errors);
+ uint res = cs->cset->well_formed_len(cs, id, id + strlen(id),
+ NAME_CHAR_LEN,
+ &well_formed_error);
- uint res = cs2->cset->well_formed_len(cs2, tmp, tmp + len,
- NAME_CHAR_LEN,
- &well_formed_error);
-
- if (well_formed_error || res != len) {
- my_error(ER_TOO_LONG_IDENT, MYF(0), tmp);
- return(true);
+ if (well_formed_error || res == NAME_CHAR_LEN) {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), id);
+ DBUG_RETURN(true);
}
- return(false);
+ DBUG_RETURN(false);
}
/******************************************************************//**
@@ -3916,7 +3910,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];
@@ -3949,22 +3942,18 @@ 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);
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
@@ -4007,11 +3996,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 "
@@ -4037,9 +4022,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"
@@ -8227,9 +8211,10 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "updating table statistics";
- dict_update_statistics(ib_table,
- FALSE /* update even if stats
- are initialized */);
+ dict_update_statistics(
+ ib_table,
+ FALSE, /* update even if initialized */
+ FALSE /* update even if not changed too much */);
prebuilt->trx->op_info = "returning various info to MySQL";
}
@@ -12123,3 +12108,55 @@ 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);
+}
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 11505121fa2..46a8d5b744c 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -4271,7 +4271,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(
/*============*/
@@ -4577,6 +4577,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;
@@ -4595,12 +4601,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));
@@ -4743,6 +4743,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);
@@ -4873,6 +4874,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/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index b7f6eae3f09..562f2f0887c 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/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
@@ -663,9 +663,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/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 54af14313c4..7b55a59ea19 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/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,10 +1144,14 @@ 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 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 */
/********************************************************************//**
Reserves the dictionary system mutex for MySQL. */
UNIV_INTERN
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 980417715b3..0ee5721d34b 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/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/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index f0a05a38070..8e3a04f7956 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/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/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index a804c261447..dd188e4dad1 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/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
@@ -326,10 +326,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 */
@@ -345,8 +347,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/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index ae0188fdaa1..dc730f9b6b3 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/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
@@ -307,4 +307,24 @@ 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/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 8ef0906ff5f..9d1b3f18f8a 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/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
***********************************************************************/
diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic
index b5480604bdf..9e9dda90936 100644
--- a/storage/innobase/include/page0zip.ic
+++ b/storage/innobase/include/page0zip.ic
@@ -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/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c
index a5ce43496af..cd9db2a02b1 100644
--- a/storage/innobase/lock/lock0lock.c
+++ b/storage/innobase/lock/lock0lock.c
@@ -4980,6 +4980,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;
@@ -5029,6 +5030,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,
@@ -5045,7 +5047,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/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c
index c4ad94a4906..814736d9b14 100644
--- a/storage/innobase/log/log0recv.c
+++ b/storage/innobase/log/log0recv.c
@@ -1648,19 +1648,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);
@@ -1677,6 +1664,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
diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c
index 7727760f1cd..797de06c896 100644
--- a/storage/innobase/mem/mem0mem.c
+++ b/storage/innobase/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/innobase/os/os0file.c b/storage/innobase/os/os0file.c
index 0d036f6f032..8fc22fbd119 100644
--- a/storage/innobase/os/os0file.c
+++ b/storage/innobase/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
***********************************************************************/
diff --git a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c
index f9338da079e..a4a357ae44a 100644
--- a/storage/innobase/page/page0zip.c
+++ b/storage/innobase/page/page0zip.c
@@ -2271,13 +2271,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)));
@@ -2428,12 +2427,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);
@@ -2759,12 +2758,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);
@@ -4639,8 +4638,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/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 21afa9eff0d..8312ef38311 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/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
@@ -1698,6 +1698,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)) {
@@ -1707,6 +1708,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
@@ -1715,13 +1726,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/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 77fa6518b35..ff8f79f4f3f 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/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
@@ -53,7 +53,7 @@ Created 9/17/2000 Heikki Tuuri
#include "ibuf0ibuf.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;
@@ -962,17 +962,12 @@ row_update_statistics_if_needed(
table->stat_modified_counter = counter + 1;
- /* 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 (counter > 2000000000
- || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
+ if (DICT_TABLE_CHANGED_TOO_MUCH(table)) {
- dict_update_statistics(table, FALSE /* update even if stats
- are initialized */);
+ dict_update_statistics(
+ table,
+ FALSE, /* update even if stats are initialized */
+ TRUE /* only update if stats changed too much */);
}
}
@@ -3050,8 +3045,10 @@ 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 */);
+ dict_update_statistics(
+ table,
+ FALSE, /* update even if stats are initialized */
+ FALSE /* update even if not changed too much */);
trx_commit_for_mysql(trx);
@@ -3959,12 +3956,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"
@@ -3976,6 +3990,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"
@@ -3984,8 +3999,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"
@@ -4002,12 +4015,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/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index 86caf9d4243..849e97b31f7 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -1719,7 +1719,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;
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index 86669a50895..d3d2e956e22 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/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.
@@ -818,6 +818,7 @@ open_or_create_data_files(
}
if (ret == FALSE) {
+ const char* check_msg;
/* We open the data file */
if (one_created) {
@@ -915,13 +916,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)) {
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
index bc51dc43032..256e22d1b50 100644
--- a/storage/innobase/trx/trx0sys.c
+++ b/storage/innobase/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
@@ -564,7 +564,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"
@@ -575,7 +576,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(