merge Percona-Server-5.5.32-rel31.0.tar.gz

This commit is contained in:
Sergei Golubchik 2013-07-16 19:30:39 +02:00
commit a5b534a08e
48 changed files with 1256 additions and 656 deletions

0
sql-bench/myisam.cnf Normal file → Executable file
View file

View file

@ -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),

View file

@ -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(&current_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,

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
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);

View file

@ -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);

View file

@ -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;

View file

@ -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,8 +4949,10 @@ 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,
@ -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

View file

@ -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 {
ut_ad(size >= free_limit);
n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
}
if (n_free_up > 0) {
n_free_up--;

View file

@ -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 =
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
*/
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<const char*const*>(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<const char*const*>(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

View file

@ -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,6 +2925,7 @@ i_s_innodb_fill_buffer_pool(
i_s_innodb_buffer_page_get_info(
&block->page, pool_id, block_id,
info_buffer + num_page);
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

View file

@ -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;
}

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.
@param arr dyn array
@param block dyn array block
@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 */
#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));
/*#################################################################*/

View file

@ -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;
}
}
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,9 +255,9 @@ 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;
const dyn_block_t* block;
ulint sum = 0;
ut_ad(arr);
@ -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 */
{

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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 */

View file

@ -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

View file

@ -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;

View file

@ -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. */

View file

@ -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();

View file

@ -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));

View file

@ -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) /*!<in: the start LSN name
part */
{
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;
}
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;
}
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) /*!<in/out: iterator */
{
ibool checksum_ok = FALSE;
ibool success;
ut_a(i);
if (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++) {

View file

@ -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()

View file

@ -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 */

View file

@ -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,73 +59,82 @@ 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)));
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);
log_flush_order_mutex_enter();
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)));
while (slot-- != start) {
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;
return;
}
}
}
log_flush_order_mutex_exit();
}
#endif /* !UNIV_HOTBACKUP */

View file

@ -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 <sys/ioctl.h>
# 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 <sys/ioctl.h>
#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)))
{
#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;
}
return(TRUE);
#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);
#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,10 +1784,12 @@ 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);
&& os_file_set_atomic_writes(name, file)) {
*success = FALSE;
close(file);
file = -1;
}
@ -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.
@ -2132,23 +2136,17 @@ os_file_set_size(
#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);
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

View file

@ -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,12 +837,13 @@ 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);
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)

View file

@ -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);
}

View file

@ -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) {

View file

@ -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"

View file

@ -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;
}
}

View file

@ -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;
@ -411,8 +411,9 @@ UNIV_INTERN ulong srv_sys_stats_root_page = 0;
UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
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) {
{
trx_id_t done_trx_no;
trx_id_t 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 - purge_sys->done_trx_no;
trx_sys->max_trx_id - done_trx_no;
}
if (!purge_sys->view
|| trx_sys->max_trx_id < purge_sys->view->up_limit_id) {
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 - purge_sys->view->up_limit_id;
trx_sys->max_trx_id - up_limit_id;
}
}
#endif /* UNIV_DEBUG */

View file

@ -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

View file

@ -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"

View file

@ -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);

View file

@ -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 = "";
}

View file

@ -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 <sys/types.h>

View file

@ -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 */
}