summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-04-05 10:49:38 +0200
committerSergei Golubchik <sergii@pisem.net>2012-04-05 10:49:38 +0200
commitdea3544b2d9bd68961b8e84c3772deda435f15b5 (patch)
treed65a66f9f2f9378a1f4ca014e18952ae514f4cb1 /storage
parentc72d5e80c53c53a9a847b1c3b6ac66a7ad7eb815 (diff)
parentceec7cea338e117d15a9679e517cc2bb24d44fcc (diff)
downloadmariadb-git-dea3544b2d9bd68961b8e84c3772deda435f15b5.tar.gz
mysql-5.1.62 merge
Diffstat (limited to 'storage')
-rw-r--r--storage/archive/ha_archive.cc8
-rw-r--r--storage/federated/Makefile.am2
-rw-r--r--storage/federated/ha_federated.cc12
-rw-r--r--storage/heap/hp_create.c2
-rw-r--r--storage/heap/hp_info.c2
-rw-r--r--storage/innobase/btr/btr0cur.c5
-rw-r--r--storage/innobase/buf/buf0buf.c8
-rw-r--r--storage/innobase/fil/fil0fil.c24
-rw-r--r--storage/innobase/handler/ha_innodb.cc222
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c10
-rw-r--r--storage/innobase/include/mem0mem.ic4
-rw-r--r--storage/innobase/include/os0proc.h11
-rw-r--r--storage/innobase/include/trx0rseg.ic9
-rw-r--r--storage/innobase/include/trx0sys.h5
-rw-r--r--storage/innobase/include/univ.i35
-rw-r--r--storage/innobase/include/ut0mem.h26
-rw-r--r--storage/innobase/include/ut0rnd.ic2
-rw-r--r--storage/innobase/mem/mem0pool.c6
-rw-r--r--storage/innobase/os/os0proc.c33
-rw-r--r--storage/innobase/row/row0ins.c11
-rw-r--r--storage/innobase/row/row0mysql.c12
-rw-r--r--storage/innobase/row/row0sel.c4
-rw-r--r--storage/innobase/row/row0upd.c10
-rw-r--r--storage/innobase/trx/trx0sys.c4
-rw-r--r--storage/innobase/ut/ut0mem.c65
-rw-r--r--storage/innodb_plugin/ChangeLog57
-rw-r--r--storage/innodb_plugin/btr/btr0btr.c153
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c258
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c7
-rw-r--r--storage/innodb_plugin/fil/fil0fil.c31
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c399
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc228
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c62
-rw-r--r--storage/innodb_plugin/include/btr0btr.h31
-rw-r--r--storage/innodb_plugin/include/btr0cur.h88
-rw-r--r--storage/innodb_plugin/include/btr0cur.ic29
-rw-r--r--storage/innodb_plugin/include/buf0buf.h31
-rw-r--r--storage/innodb_plugin/include/buf0buf.ic19
-rw-r--r--storage/innodb_plugin/include/fsp0fsp.h43
-rw-r--r--storage/innodb_plugin/include/log0log.h6
-rw-r--r--storage/innodb_plugin/include/mem0mem.ic4
-rw-r--r--storage/innodb_plugin/include/mtr0mtr.h17
-rw-r--r--storage/innodb_plugin/include/mtr0mtr.ic7
-rw-r--r--storage/innodb_plugin/include/page0page.h43
-rw-r--r--storage/innodb_plugin/include/page0page.ic36
-rw-r--r--storage/innodb_plugin/include/trx0rec.ic7
-rw-r--r--storage/innodb_plugin/include/trx0rseg.ic9
-rw-r--r--storage/innodb_plugin/include/trx0sys.h6
-rw-r--r--storage/innodb_plugin/include/trx0undo.h13
-rw-r--r--storage/innodb_plugin/include/univ.i17
-rw-r--r--storage/innodb_plugin/include/ut0mem.h31
-rw-r--r--storage/innodb_plugin/include/ut0rnd.ic2
-rw-r--r--storage/innodb_plugin/log/log0log.c6
-rw-r--r--storage/innodb_plugin/mem/mem0pool.c6
-rw-r--r--storage/innodb_plugin/mtr/mtr0mtr.c4
-rw-r--r--storage/innodb_plugin/os/os0proc.c3
-rw-r--r--storage/innodb_plugin/page/page0cur.c21
-rw-r--r--storage/innodb_plugin/page/page0page.c56
-rw-r--r--storage/innodb_plugin/row/row0ins.c92
-rw-r--r--storage/innodb_plugin/row/row0merge.c35
-rw-r--r--storage/innodb_plugin/row/row0mysql.c14
-rw-r--r--storage/innodb_plugin/row/row0row.c33
-rw-r--r--storage/innodb_plugin/row/row0sel.c4
-rw-r--r--storage/innodb_plugin/row/row0upd.c73
-rw-r--r--storage/innodb_plugin/trx/trx0rec.c38
-rw-r--r--storage/innodb_plugin/trx/trx0sys.c29
-rw-r--r--storage/innodb_plugin/trx/trx0trx.c2
-rw-r--r--storage/innodb_plugin/trx/trx0undo.c43
-rw-r--r--storage/innodb_plugin/ut/ut0mem.c82
-rw-r--r--storage/myisam/ft_boolean_search.c3
-rw-r--r--storage/myisam/ft_nlq_search.c2
-rw-r--r--storage/myisam/mi_check.c18
-rw-r--r--storage/myisam/mi_close.c3
-rw-r--r--storage/myisam/mi_delete_all.c2
-rw-r--r--storage/myisam/mi_packrec.c3
-rw-r--r--storage/myisam/mi_preload.c3
-rw-r--r--storage/xtradb/row/row0sel.c4
77 files changed, 1763 insertions, 982 deletions
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 618fc1ea7f3..ea778cd23a8 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004, 2011, Oracle and/or its affiliates
+ Copyright (c) 2004, 2012, Oracle and/or its affiliates
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -1319,6 +1319,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
azio_stream writer;
char writer_filename[FN_REFLEN];
+ pthread_mutex_lock(&share->mutex);
init_archive_reader();
// now we close both our writer and our reader for the rename
@@ -1333,7 +1334,10 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY)))
+ {
+ pthread_mutex_unlock(&share->mutex);
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ }
/*
An extended rebuild is a lot more effort. We open up each row and re-record it.
@@ -1412,10 +1416,12 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
rc = my_rename(writer_filename,share->data_file_name,MYF(0));
+ pthread_mutex_unlock(&share->mutex);
DBUG_RETURN(rc);
error:
DBUG_PRINT("ha_archive", ("Failed to recover, error was %d", rc));
azclose(&writer);
+ pthread_mutex_unlock(&share->mutex);
DBUG_RETURN(rc);
}
diff --git a/storage/federated/Makefile.am b/storage/federated/Makefile.am
index 31778a24550..409f4ea022e 100644
--- a/storage/federated/Makefile.am
+++ b/storage/federated/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates
+# Copyright (c) 2006, 2011, Oracle and/or its affiliates
#
# 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
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 4449dc576eb..e63645caf76 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004, 2010, Oracle and/or its affiliates
+/* Copyright (c) 2004, 2011, Oracle and/or its affiliates
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
@@ -1651,6 +1651,16 @@ int ha_federated::close(void)
mysql_close(mysql);
mysql= NULL;
+ /*
+ mysql_close() might return an error if a remote server's gone
+ for some reason. If that happens while removing a table from
+ the table cache, the error will be propagated to a client even
+ if the original query was not issued against the FEDERATED table.
+ So, don't propagate errors from mysql_close().
+ */
+ if (table->in_use)
+ table->in_use->clear_error();
+
DBUG_RETURN(free_share(share));
}
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index 5208d4676c3..c1be34b6b0d 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (c) 2000, 2011, 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
diff --git a/storage/heap/hp_info.c b/storage/heap/hp_info.c
index c72dbaf2065..17f8c3fe97a 100644
--- a/storage/heap/hp_info.c
+++ b/storage/heap/hp_info.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2004 MySQL AB
+/* Copyright (c) 2000, 2011, 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
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 3c12e28feb6..c09d6408fa0 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -321,7 +321,12 @@ btr_cur_search_to_nth_level(
ut_ad(dict_index_check_search_tuple(index, tuple));
ut_ad(!(index->type & DICT_IBUF) || ibuf_inside());
ut_ad(dtuple_check_typed(tuple));
+ ut_ad(index->page != FIL_NULL);
+ UNIV_MEM_INVALID(&cursor->up_match, sizeof cursor->up_match);
+ UNIV_MEM_INVALID(&cursor->up_bytes, sizeof cursor->up_bytes);
+ UNIV_MEM_INVALID(&cursor->low_match, sizeof cursor->low_match);
+ UNIV_MEM_INVALID(&cursor->low_bytes, sizeof cursor->low_bytes);
#ifdef UNIV_DEBUG
cursor->up_match = ULINT_UNDEFINED;
cursor->low_match = ULINT_UNDEFINED;
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 78b39812cff..5463098a654 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -634,7 +634,7 @@ buf_pool_init(
/*----------------------------------------*/
} else {
buf_pool->frame_mem = os_mem_alloc_large(
- UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE);
+ UNIV_PAGE_SIZE * (n_frames + 1), FALSE);
}
if (buf_pool->frame_mem == NULL) {
@@ -756,12 +756,8 @@ buf_pool_init(
block = buf_pool_get_nth_block(buf_pool, i);
if (block->frame) {
- /* Wipe contents of frame to eliminate a Purify
- warning */
+ UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
-#ifdef HAVE_purify
- memset(block->frame, '\0', UNIV_PAGE_SIZE);
-#endif
if (srv_use_awe) {
/* Add to the list of blocks mapped to
frames */
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index 6ca8381ebdf..1d3cdc6e227 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -772,11 +772,6 @@ retry:
return;
}
- if (system->n_open < system->max_n_open) {
-
- return;
- }
-
HASH_SEARCH(hash, system->spaces, space_id, space,
space->id == space_id);
if (space != NULL && space->stop_ios) {
@@ -793,6 +788,18 @@ retry:
mutex_exit(&(system->mutex));
+#ifndef UNIV_HOTBACKUP
+ /* Wake the i/o-handler threads to make sure pending
+ i/o's are performed */
+ os_aio_simulated_wake_handler_threads();
+
+ os_thread_sleep(20000);
+#endif /* UNIV_HOTBACKUP */
+
+ /* Flush tablespaces so that we can close modified
+ files in the LRU list */
+ fil_flush_file_spaces(FIL_TABLESPACE);
+
os_thread_sleep(20000);
count2++;
@@ -800,6 +807,11 @@ retry:
goto retry;
}
+ if (system->n_open < system->max_n_open) {
+
+ return;
+ }
+
/* If the file is already open, no need to do anything; if the space
does not exist, we handle the situation in the function which called
this function */
@@ -2290,7 +2302,7 @@ fil_rename_tablespace(
retry:
count++;
- if (count > 1000) {
+ if (!(count % 1000)) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: problems renaming ", stderr);
ut_print_filename(stderr, old_name);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index a4d79a5934e..20ab9c7a101 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -948,6 +948,19 @@ innobase_get_charset(
return(thd_charset((THD*) mysql_thd));
}
+/**********************************************************************//**
+Get the current setting of the lower_case_table_names global parameter from
+mysqld.cc. We do a dirty read because for one there is no synchronization
+object and secondly there is little harm in doing so even if we get a torn
+read.
+@return value of lower_case_table_names */
+ulint
+innobase_get_lower_case_table_names(void)
+/*=====================================*/
+{
+ return(lower_case_table_names);
+}
+
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
/*******************************************************************//**
@@ -2579,52 +2592,139 @@ ha_innobase::bas_ext() const
return ha_innobase_exts;
}
+/** Always normalize table name to lower case on Windows */
+#ifdef __WIN__
+#define normalize_table_name(norm_name, name) \
+ normalize_table_name_low(norm_name, name, TRUE)
+#else
+#define normalize_table_name(norm_name, name) \
+ normalize_table_name_low(norm_name, name, FALSE)
+#endif /* __WIN__ */
/*********************************************************************
Normalizes a table name string. A normalized name consists of the
database name catenated to '/' and table name. An example:
test/mytable. On Windows normalization puts both the database name and the
-table name always to lower case. */
+table name always to lower case if "set_lower_case" is set to TRUE. */
static
void
-normalize_table_name(
-/*=================*/
+normalize_table_name_low(
+/*=====================*/
char* norm_name, /* out: normalized name as a
null-terminated string */
- const char* name) /* in: table name string */
+ const char* name, /* in: table name string */
+ ibool set_lower_case) /* in: TRUE if we want to set
+ name to lower case */
{
char* name_ptr;
char* db_ptr;
+ ulint db_len;
char* ptr;
/* Scan name from the end */
- ptr = strend(name)-1;
+ ptr = strend(name) - 1;
+ /* seek to the last path separator */
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--;
}
name_ptr = ptr + 1;
- DBUG_ASSERT(ptr > name);
+ /* skip any number of path separators */
+ while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
+ ptr--;
+ }
- ptr--;
+ DBUG_ASSERT(ptr >= name);
+ /* seek to the last but one path separator or one char before
+ the beginning of name */
+ db_len = 0;
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--;
+ db_len++;
}
db_ptr = ptr + 1;
- memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
+ memcpy(norm_name, db_ptr, db_len);
- norm_name[name_ptr - db_ptr - 1] = '/';
+ norm_name[db_len] = '/';
-#ifdef __WIN__
- innobase_casedn_str(norm_name);
-#endif
+ memcpy(norm_name + db_len + 1, name_ptr, strlen(name_ptr) + 1);
+
+ if (set_lower_case) {
+ innobase_casedn_str(norm_name);
+ }
+}
+
+#if !defined(DBUG_OFF)
+/*********************************************************************
+Test normalize_table_name_low(). */
+static
+void
+test_normalize_table_name_low()
+/*===========================*/
+{
+ char norm_name[128];
+ const char* test_data[][2] = {
+ /* input, expected result */
+ {"./mysqltest/t1", "mysqltest/t1"},
+ {"./test/#sql-842b_2", "test/#sql-842b_2"},
+ {"./test/#sql-85a3_10", "test/#sql-85a3_10"},
+ {"./test/#sql2-842b-2", "test/#sql2-842b-2"},
+ {"./test/bug29807", "test/bug29807"},
+ {"./test/foo", "test/foo"},
+ {"./test/innodb_bug52663", "test/innodb_bug52663"},
+ {"./test/t", "test/t"},
+ {"./test/t1", "test/t1"},
+ {"./test/t10", "test/t10"},
+ {"/a/b/db/table", "db/table"},
+ {"/a/b/db///////table", "db/table"},
+ {"/a/b////db///////table", "db/table"},
+ {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
+ {"db/table", "db/table"},
+ {"ddd/t", "ddd/t"},
+ {"d/ttt", "d/ttt"},
+ {"d/t", "d/t"},
+ {".\\mysqltest\\t1", "mysqltest/t1"},
+ {".\\test\\#sql-842b_2", "test/#sql-842b_2"},
+ {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
+ {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
+ {".\\test\\bug29807", "test/bug29807"},
+ {".\\test\\foo", "test/foo"},
+ {".\\test\\innodb_bug52663", "test/innodb_bug52663"},
+ {".\\test\\t", "test/t"},
+ {".\\test\\t1", "test/t1"},
+ {".\\test\\t10", "test/t10"},
+ {"C:\\a\\b\\db\\table", "db/table"},
+ {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
+ {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
+ {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
+ {"db\\table", "db/table"},
+ {"ddd\\t", "ddd/t"},
+ {"d\\ttt", "d/ttt"},
+ {"d\\t", "d/t"},
+ };
+
+ for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
+ printf("test_normalize_table_name_low(): "
+ "testing \"%s\", expected \"%s\"... ",
+ test_data[i][0], test_data[i][1]);
+
+ normalize_table_name_low(norm_name, test_data[i][0], FALSE);
+
+ if (strcmp(norm_name, test_data[i][1]) == 0) {
+ printf("ok\n");
+ } else {
+ printf("got \"%s\"\n", norm_name);
+ ut_error;
+ }
+ }
}
+#endif /* !DBUG_OFF */
/************************************************************************
Get the upper limit of the MySQL integral and floating-point type. */
@@ -2806,6 +2906,8 @@ ha_innobase::open(
THD* thd;
ulint retries = 0;
char* is_part = NULL;
+ ibool par_case_name_set = FALSE;
+ char par_case_name[MAX_FULL_NAME_LEN + 1];
DBUG_ENTER("ha_innobase::open");
@@ -2852,16 +2954,87 @@ ha_innobase::open(
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. */
+#ifdef __WIN__
+ is_part = strstr(norm_name, "#p#");
+#else
is_part = strstr(norm_name, "#P#");
+#endif /* __WIN__ */
+
retry:
/* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get(norm_name, TRUE);
-
+
if (NULL == ib_table) {
if (is_part && retries < 10) {
- ++retries;
- os_thread_sleep(100000);
- goto retry;
+ /* 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
+ for sub-partition names as well. InnoDB always
+ normalises file names to lower case on Windows, this
+ can potentially cause problems when copying/moving
+ tables between platforms.
+
+ 1) If boot against an installation from Windows
+ platform, then its partition table name could
+ be all be in lower case in system tables. So we
+ will need to check lower case name when load table.
+
+ 2) If we boot an installation from other case
+ sensitive platform in Windows, we might need to
+ check the existence of table name without lowering
+ case them in the system table. */
+ if (innobase_get_lower_case_table_names() == 1) {
+
+ if (!par_case_name_set) {
+#ifndef __WIN__
+ /* Check for the table using lower
+ case name, including the partition
+ separator "P" */
+ memcpy(par_case_name, norm_name,
+ strlen(norm_name));
+ par_case_name[strlen(norm_name)] = 0;
+ innobase_casedn_str(par_case_name);
+#else
+ /* On Windows platfrom, check
+ whether there exists table name in
+ system table whose name is
+ not being normalized to lower case */
+ normalize_table_name_low(
+ par_case_name, name, FALSE);
+#endif
+ par_case_name_set = TRUE;
+ }
+
+ ib_table = dict_table_get(
+ par_case_name, FALSE);
+ }
+ if (!ib_table) {
+ ++retries;
+ os_thread_sleep(100000);
+ goto retry;
+ } else {
+#ifndef __WIN__
+ sql_print_warning("Partition table %s opened "
+ "after converting to lower "
+ "case. The table may have "
+ "been moved from a case "
+ "in-sensitive file system. "
+ "Please recreate table in "
+ "the current file system\n",
+ norm_name);
+#else
+ sql_print_warning("Partition table %s opened "
+ "after skipping the step to "
+ "lower case the table name. "
+ "The table may have been "
+ "moved from a case sensitive "
+ "file system. Please "
+ "recreate table in the "
+ "current file system\n",
+ norm_name);
+#endif
+ goto table_opened;
+ }
}
if (is_part) {
@@ -2892,6 +3065,8 @@ retry:
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
+table_opened:
+
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
sql_print_error("MySQL is trying to open a table handle but "
"the .ibd file for\ntable %s does not exist.\n"
@@ -5892,6 +6067,11 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ DBUG_EXECUTE_IF(
+ "test_normalize_table_name_low",
+ test_normalize_table_name_low();
+ );
+
/* Strangely, MySQL passes the table name without the '.frm'
extension, in contrast to ::create */
normalize_table_name(norm_name, name);
@@ -9060,6 +9240,13 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
NULL, NULL, 0, 0, 1, 0);
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+#ifdef UNIV_DEBUG
+static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
+ PLUGIN_VAR_RQCMDARG,
+ "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
+ NULL, NULL, 0, 0, 1024, 0);
+#endif /* UNIV_DEBUG */
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
@@ -9105,6 +9292,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
MYSQL_SYSVAR(change_buffering_debug),
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+#ifdef UNIV_DEBUG
+ MYSQL_SYSVAR(trx_rseg_n_slots_debug),
+#endif /* UNIV_DEBUG */
NULL
};
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 1406b2de4e9..476d78e79ba 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -2009,7 +2009,15 @@ ibuf_get_merge_page_nos(
} else {
rec_page_no = ibuf_rec_get_page_no(rec);
rec_space_id = ibuf_rec_get_space(rec);
- ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
+ /* In the system tablespace, the smallest
+ possible secondary index leaf page number is
+ bigger than IBUF_TREE_ROOT_PAGE_NO (4). In
+ other tablespaces, the clustered index tree is
+ created at page 3, which makes page 4 the
+ smallest possible secondary index leaf page
+ (and that only after DROP INDEX). */
+ ut_ad(rec_page_no
+ > IBUF_TREE_ROOT_PAGE_NO - (rec_space_id != 0));
}
#ifdef UNIV_IBUF_DEBUG
diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic
index 782672dbc18..0191e9a3ffd 100644
--- a/storage/innobase/include/mem0mem.ic
+++ b/storage/innobase/include/mem0mem.ic
@@ -195,10 +195,6 @@ mem_heap_alloc(
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
#endif
-#ifdef UNIV_SET_MEM_TO_ZERO
- UNIV_MEM_ALLOC(buf, n);
- memset(buf, '\0', n);
-#endif
UNIV_MEM_ALLOC(buf, n);
return(buf);
}
diff --git a/storage/innobase/include/os0proc.h b/storage/innobase/include/os0proc.h
index f54e08de7ee..8c169f92431 100644
--- a/storage/innobase/include/os0proc.h
+++ b/storage/innobase/include/os0proc.h
@@ -104,14 +104,6 @@ ulint
os_proc_get_number(void);
/*====================*/
/********************************************************************
-Allocates non-cacheable memory. */
-
-void*
-os_mem_alloc_nocache(
-/*=================*/
- /* out: allocated memory */
- ulint n); /* in: number of bytes */
-/********************************************************************
Allocates large pages memory. */
void*
@@ -119,9 +111,6 @@ os_mem_alloc_large(
/*===============*/
/* out: allocated memory */
ulint n, /* in: number of bytes */
- ibool set_to_zero, /* in: TRUE if allocated memory
- should be set to zero if
- UNIV_SET_MEM_TO_ZERO is defined */
ibool assert_on_error);/* in: if TRUE, we crash mysqld if
the memory cannot be allocated */
/********************************************************************
diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic
index 577cd0dee7b..5b01b2f197d 100644
--- a/storage/innobase/include/trx0rseg.ic
+++ b/storage/innobase/include/trx0rseg.ic
@@ -8,6 +8,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "mtr0log.h"
+#include "trx0sys.h"
/**********************************************************************
Gets a rollback segment header. */
@@ -113,7 +114,13 @@ trx_rsegf_undo_find_free(
ulint i;
ulint page_no;
- for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
+ for (i = 0;
+#ifndef UNIV_DEBUG
+ i < TRX_RSEG_N_SLOTS;
+#else
+ i < (trx_rseg_n_slots_debug ? trx_rseg_n_slots_debug : TRX_RSEG_N_SLOTS);
+#endif
+ i++) {
page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr);
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 7ea981eb85c..aedeb51d3b3 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -47,6 +47,11 @@ extern ibool trx_doublewrite_buf_is_being_created;
extern ibool trx_doublewrite_must_reset_space_ids;
extern ibool trx_sys_multiple_tablespace_format;
+#ifdef UNIV_DEBUG
+/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
+extern uint trx_rseg_n_slots_debug;
+#endif
+
/********************************************************************
Creates the doublewrite buffer to a new InnoDB installation. The header of the
doublewrite buffer is placed on the trx system header page. */
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index a67b1b3895e..804f0e35605 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -72,14 +72,6 @@ Microsoft Visual C++ */
/* DEBUG VERSION CONTROL
===================== */
-/* The following flag will make InnoDB to initialize
-all memory it allocates to zero. It hides Purify
-warnings about reading unallocated memory unless
-memory is read outside the allocated blocks. */
-/*
-#define UNIV_INIT_MEM_TO_ZERO
-*/
-
/* Make a non-inline debug version */
#if defined HAVE_VALGRIND
@@ -112,15 +104,6 @@ operations (very slow); also UNIV_DEBUG must be defined */
#define UNIV_BTR_DEBUG /* check B-tree links */
#define UNIV_LIGHT_MEM_DEBUG /* light memory debugging */
-#ifdef HAVE_purify
-/* The following sets all new allocated memory to zero before use:
-this can be used to eliminate unnecessary Purify warnings, but note that
-it also masks many bugs Purify could detect. For detailed Purify analysis it
-is best to remove the define below and look through the warnings one
-by one. */
-#define UNIV_SET_MEM_TO_ZERO
-#endif
-
/*
#define UNIV_SQL_DEBUG
#define UNIV_LOG_DEBUG
@@ -177,6 +160,24 @@ management to ensure correct alignment for doubles etc. */
/* Maximum number of parallel threads in a parallelized operation */
#define UNIV_MAX_PARALLELISM 32
+/** The maximum length of a table name. This is the MySQL limit and is
+defined in mysql_com.h like NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN, the
+number does not include a terminating '\0'. InnoDB probably can handle
+longer names internally */
+#define MAX_TABLE_NAME_LEN 192
+
+/** The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
+the MySQL's NAME_LEN, see check_and_convert_db_name(). */
+#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
+
+/** MAX_FULL_NAME_LEN defines the full name path including the
+database name and table name. In addition, 14 bytes is added for:
+ 2 for surrounding quotes around table name
+ 1 for the separating dot (.)
+ 9 for the #mysql50# prefix */
+#define MAX_FULL_NAME_LEN \
+ (MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
+
/*
UNIVERSAL TYPE DEFINITIONS
==========================
diff --git a/storage/innobase/include/ut0mem.h b/storage/innobase/include/ut0mem.h
index cb369e85c39..0dff70abc3a 100644
--- a/storage/innobase/include/ut0mem.h
+++ b/storage/innobase/include/ut0mem.h
@@ -30,38 +30,18 @@ ut_memcmp(const void* str1, const void* str2, ulint n);
/**************************************************************************
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined and set_to_zero is TRUE. */
+Allocates memory. */
void*
ut_malloc_low(
/*==========*/
/* out, own: allocated memory */
ulint n, /* in: number of bytes to allocate */
- ibool set_to_zero, /* in: TRUE if allocated memory
- should be set to zero if
- UNIV_SET_MEM_TO_ZERO is defined */
ibool assert_on_error); /* in: if TRUE, we crash mysqld if
the memory cannot be allocated */
/**************************************************************************
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined. */
-
-void*
-ut_malloc(
-/*======*/
- /* out, own: allocated memory */
- ulint n); /* in: number of bytes to allocate */
-/**************************************************************************
-Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
-out. It cannot be used if we want to return an error message. Prints to
-stderr a message if fails. */
-
-ibool
-ut_test_malloc(
-/*===========*/
- /* out: TRUE if succeeded */
- ulint n); /* in: try to allocate this many bytes */
+Allocates memory. */
+#define ut_malloc(n) ut_malloc_low(n, TRUE)
/**************************************************************************
Frees a memory block allocated with ut_malloc. */
diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic
index dc4c0d62f56..b54f629de37 100644
--- a/storage/innobase/include/ut0rnd.ic
+++ b/storage/innobase/include/ut0rnd.ic
@@ -96,7 +96,7 @@ ut_rnd_interval(
rnd = ut_rnd_gen_ulint();
- return(low + (rnd % (high - low + 1)));
+ return(low + (rnd % (high - low)));
}
/*************************************************************
diff --git a/storage/innobase/mem/mem0pool.c b/storage/innobase/mem/mem0pool.c
index 27da86a0309..6740ff04a4f 100644
--- a/storage/innobase/mem/mem0pool.c
+++ b/storage/innobase/mem/mem0pool.c
@@ -196,11 +196,7 @@ mem_pool_create(
pool = ut_malloc(sizeof(mem_pool_t));
- /* We do not set the memory to zero (FALSE) in the pool,
- but only when allocated at a higher level in mem0mem.c.
- This is to avoid masking useful Purify warnings. */
-
- pool->buf = ut_malloc_low(size, FALSE, TRUE);
+ pool->buf = ut_malloc_low(size, TRUE);
pool->size = size;
mutex_create(&pool->mutex, SYNC_MEM_POOL);
diff --git a/storage/innobase/os/os0proc.c b/storage/innobase/os/os0proc.c
index f00475fc528..6092392616f 100644
--- a/storage/innobase/os/os0proc.c
+++ b/storage/innobase/os/os0proc.c
@@ -532,28 +532,6 @@ os_proc_get_number(void)
}
/********************************************************************
-Allocates non-cacheable memory. */
-
-void*
-os_mem_alloc_nocache(
-/*=================*/
- /* out: allocated memory */
- ulint n) /* in: number of bytes */
-{
-#ifdef __WIN__
- void* ptr;
-
- ptr = VirtualAlloc(NULL, n, MEM_COMMIT,
- PAGE_READWRITE | PAGE_NOCACHE);
- ut_a(ptr);
-
- return(ptr);
-#else
- return(ut_malloc(n));
-#endif
-}
-
-/********************************************************************
Allocates large pages memory. */
void*
@@ -561,9 +539,6 @@ os_mem_alloc_large(
/*===============*/
/* out: allocated memory */
ulint n, /* in: number of bytes */
- ibool set_to_zero, /* in: TRUE if allocated memory
- should be set to zero if
- UNIV_SET_MEM_TO_ZERO is defined */
ibool assert_on_error)/* in: if TRUE, we crash mysqld if
the memory cannot be allocated */
{
@@ -602,12 +577,6 @@ os_mem_alloc_large(
#endif
if (ptr) {
- if (set_to_zero) {
-#ifdef UNIV_SET_MEM_TO_ZERO
- memset(ptr, '\0', size);
-#endif
- }
-
return(ptr);
}
@@ -616,7 +585,7 @@ os_mem_alloc_large(
skip:
#endif /* HAVE_LARGE_PAGES */
- return(ut_malloc_low(n, set_to_zero, assert_on_error));
+ return(ut_malloc_low(n, assert_on_error));
}
/********************************************************************
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index db134ca7a41..bb5c95a572b 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -6,6 +6,9 @@ Insert into a table
Created 4/20/1996 Heikki Tuuri
*******************************************************/
+#include "my_global.h" /* HAVE_* */
+#include "m_string.h" /* for my_sys.h */
+#include "my_sys.h" /* DEBUG_SYNC_C */
#include "row0ins.h"
#ifdef UNIV_NONINL
@@ -2121,16 +2124,24 @@ function_exit:
if (big_rec) {
rec_t* rec;
+
+ DBUG_EXECUTE_IF(
+ "row_ins_extern_checkpoint",
+ log_make_checkpoint_at(ut_dulint_max, TRUE););
+
mtr_start(&mtr);
+ DEBUG_SYNC_C("before_row_ins_extern_latch");
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0, &mtr);
rec = btr_cur_get_rec(&cursor);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
+ DEBUG_SYNC_C("before_row_ins_upd_extern");
err = btr_store_big_rec_extern_fields(index, rec,
offsets, big_rec, &mtr);
+ DEBUG_SYNC_C("after_row_ins_upd_extern");
if (modify) {
dtuple_big_rec_free(big_rec);
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index cee97871470..6148b01af9d 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -1948,6 +1948,18 @@ row_create_table_for_mysql(
FALSE);
}
+ } else if (err == DB_TOO_MANY_CONCURRENT_TRXS) {
+ /* We already have .ibd file here. it should be deleted. */
+ if (table->space
+ && !fil_delete_tablespace(table->space)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: not able to"
+ " delete tablespace %lu of table ",
+ (ulong) table->space);
+ ut_print_name(stderr, trx, TRUE, table->name);
+ fputs("!\n", stderr);
+ }
} else if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index 9ab6424a012..915cc8339d4 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -4208,7 +4208,9 @@ no_gap_lock:
applicable to unique secondary indexes. Current behaviour is
to widen the scope of a lock on an already delete marked record
if the same record is deleted twice by the same transaction */
- if (index == clust_index && unique_search) {
+ if (index == clust_index && unique_search
+ && !prebuilt->used_in_HANDLER) {
+
err = DB_RECORD_NOT_FOUND;
goto normal_return;
diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
index 0790cfe02e2..d3ed71089a8 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -6,6 +6,9 @@ Update of a row
Created 12/27/1996 Heikki Tuuri
*******************************************************/
+#include "my_global.h" /* HAVE_* */
+#include "m_string.h" /* for my_sys.h */
+#include "my_sys.h" /* DEBUG_SYNC_C */
#include "row0upd.h"
#ifdef UNIV_NONINL
@@ -1591,15 +1594,20 @@ row_upd_clust_rec(
rec_t* rec;
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
- mtr_start(mtr);
+ DBUG_EXECUTE_IF(
+ "row_upd_extern_checkpoint",
+ log_make_checkpoint_at(ut_dulint_max, TRUE););
+ mtr_start(mtr);
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
rec = btr_cur_get_rec(btr_cur);
+ DEBUG_SYNC_C("before_row_upd_extern");
err = btr_store_big_rec_extern_fields(
index, rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
big_rec, mtr);
+ DEBUG_SYNC_C("after_row_upd_extern");
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
index 137771b71ed..09b1b5d8198 100644
--- a/storage/innobase/trx/trx0sys.c
+++ b/storage/innobase/trx/trx0sys.c
@@ -54,6 +54,10 @@ InnoDB. */
char trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
ib_longlong trx_sys_mysql_bin_log_pos = -1;
+#ifdef UNIV_DEBUG
+/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
+uint trx_rseg_n_slots_debug = 0;
+#endif
/********************************************************************
Determines if a page number is located inside the doublewrite buffer. */
diff --git a/storage/innobase/ut/ut0mem.c b/storage/innobase/ut/ut0mem.c
index 2e0dd27edf4..55f1c8593b8 100644
--- a/storage/innobase/ut/ut0mem.c
+++ b/storage/innobase/ut/ut0mem.c
@@ -54,17 +54,13 @@ ut_mem_block_list_init(void)
}
/**************************************************************************
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined and set_to_zero is TRUE. */
+Allocates memory. */
void*
ut_malloc_low(
/*==========*/
/* out, own: allocated memory */
ulint n, /* in: number of bytes to allocate */
- ibool set_to_zero, /* in: TRUE if allocated memory should be
- set to zero if UNIV_SET_MEM_TO_ZERO is
- defined */
ibool assert_on_error)/* in: if TRUE, we crash mysqld if the
memory cannot be allocated */
{
@@ -156,12 +152,6 @@ retry:
#endif
}
- if (set_to_zero) {
-#ifdef UNIV_SET_MEM_TO_ZERO
- memset(ret, '\0', n + sizeof(ut_mem_block_t));
-#endif
- }
-
UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
@@ -177,59 +167,6 @@ retry:
}
/**************************************************************************
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined. */
-
-void*
-ut_malloc(
-/*======*/
- /* out, own: allocated memory */
- ulint n) /* in: number of bytes to allocate */
-{
- return(ut_malloc_low(n, TRUE, TRUE));
-}
-
-/**************************************************************************
-Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
-out. It cannot be used if we want to return an error message. Prints to
-stderr a message if fails. */
-
-ibool
-ut_test_malloc(
-/*===========*/
- /* out: TRUE if succeeded */
- ulint n) /* in: try to allocate this many bytes */
-{
- void* ret;
-
- ret = malloc(n);
-
- if (ret == NULL) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: cannot allocate"
- " %lu bytes of memory for\n"
- "InnoDB: a BLOB with malloc! Total allocated memory\n"
- "InnoDB: by InnoDB %lu bytes."
- " Operating system errno: %d\n"
- "InnoDB: Check if you should increase"
- " the swap file or\n"
- "InnoDB: ulimits of your operating system.\n"
- "InnoDB: On FreeBSD check you have"
- " compiled the OS with\n"
- "InnoDB: a big enough maximum process size.\n",
- (ulong) n,
- (ulong) ut_total_allocated_memory,
- (int) errno);
- return(FALSE);
- }
-
- free(ret);
-
- return(TRUE);
-}
-
-/**************************************************************************
Frees a memory block allocated with ut_malloc. */
void
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index d836b390c52..e1b241a5018 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,8 +1,57 @@
+2012-02-15 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c, ibuf/ibuf0ibuf.c,
+ include/btr0btr.h, include/btr0cur.h, include/btr0cur.ic,
+ include/buf0buf.h, include/buf0buf.ic, include/fsp0fsp.h,
+ include/mtr0mtr.h, include/mtr0mtr.ic, include/page0page.h,
+ include/page0page.ic, include/trx0rec.ic, include/trx0undo.h,
+ mtr/mtr0mtr.c, page/page0cur.c, page/page0page.c, row/row0ins.c,
+ row/row0row.c, row/row0upd.c, trx/trx0rec.c, trx/trx0sys.c,
+ trx/trx0undo.c:
+ Fix Bug#13721257 RACE CONDITION IN UPDATES OR INSERTS OF WIDE RECORDS
+
+2012-02-06 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#11754376 45976: INNODB LOST FILES FOR TEMPORARY TABLES ON
+ GRACEFUL SHUTDOWN
+
+2012-01-30 The InnoDB Team
+
+ * fil/fil0fil.c:
+ Fix Bug#13636122 THE ORIGINAL TABLE MISSING WHILE EXECUTE THE
+ DDL 'ALTER TABLE ADD COLUMN'
+
+2012-01-16 The InnoDB Team
+
+ * ibuf/ibuf0ibuf.c:
+ Fix Bug#13496818 ASSERTION: REC_PAGE_NO > 4 IN IBUF CONTRACTION
+
+2012-01-16 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#11765438: 58406: ISSUES WITH COPYING PARTITIONED INNODB
+ TABLES FROM LINUX TO WINDOWS
+
+2012-01-04 The InnoDB Team
+
+ * row/row0mysql.c:
+ Fix Bug#12400341: INNODB CAN LEAVE ORPHAN IBD FILES AROUND
+
+2011-12-22 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#63775 Server crash on handler read next after delete record.
+2011-12-21 The InnoDB Team
+
+ * include/ut0rnd.ic:
+ Fix Bug#11866367:FPE WHEN SETTING INNODB_SPIN_WAIT_DELAY
+
2011-12-13 The InnoDB Team
* handler/ha_innodb.cc, innodb.test, innodb.result:
- Fix Bug#13117023: InnoDB was incrementing the handler_read_key,
- also the SSV::ha_read_key_count, at the wrong place.
+ Fix Bug#13117023: InnoDB was incrementing the handler_read_key,
+ also the SSV::ha_read_key_count, at the wrong place.
2011-12-10 The InnoDB Team
@@ -263,7 +312,7 @@
2011-01-06 The InnoDB Team
* dict/dict0dict.c, handler/ha_innodb.cc, handler/i_s.cc,
- include/univ.i:
+ include/univ.i:
Fix Bug#58643 InnoDB: too long table name
2011-01-06 The InnoDB Team
@@ -529,7 +578,7 @@
* handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c:
Fix Bug#53592: crash replacing duplicates into table after fast
- alter table added unique key
+ alter table added unique key
2010-05-24 The InnoDB Team
diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c
index 23729c12c1a..20eb30588fa 100644
--- a/storage/innodb_plugin/btr/btr0btr.c
+++ b/storage/innodb_plugin/btr/btr0btr.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -906,28 +906,31 @@ btr_page_alloc_for_ibuf(
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
-@return new allocated block, x-latched; NULL if out of space */
-UNIV_INTERN
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+static __attribute__((nonnull, warn_unused_result))
buf_block_t*
-btr_page_alloc(
-/*===========*/
+btr_page_alloc_low(
+/*===============*/
dict_index_t* index, /*!< in: index */
ulint hint_page_no, /*!< in: hint of a good page */
byte file_direction, /*!< in: direction where a possible
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mtr or another
+ mini-transaction in which the
+ page should be initialized.
+ If init_mtr!=mtr, but the page
+ is already X-latched in mtr, do
+ not initialize the page. */
{
fseg_header_t* seg_header;
page_t* root;
- buf_block_t* new_block;
- ulint new_page_no;
-
- if (dict_index_is_ibuf(index)) {
-
- return(btr_page_alloc_for_ibuf(index, mtr));
- }
root = btr_root_get(index, mtr);
@@ -941,17 +944,47 @@ btr_page_alloc(
reservation for free extents, and thus we know that a page can
be allocated: */
- new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
- file_direction, TRUE, mtr);
- if (new_page_no == FIL_NULL) {
+ return(fseg_alloc_free_page_general(
+ seg_header, hint_page_no, file_direction,
+ TRUE, mtr, init_mtr));
+}
- return(NULL);
+/**************************************************************//**
+Allocates a new file page to be used in an index tree. NOTE: we assume
+that the caller has made the reservation for free extents!
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+UNIV_INTERN
+buf_block_t*
+btr_page_alloc(
+/*===========*/
+ dict_index_t* index, /*!< in: index */
+ ulint hint_page_no, /*!< in: hint of a good page */
+ byte file_direction, /*!< in: direction where a possible
+ page split is made */
+ ulint level, /*!< in: level where the page is placed
+ in the tree */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ for x-latching and initializing
+ the page */
+{
+ buf_block_t* new_block;
+
+ if (dict_index_is_ibuf(index)) {
+
+ return(btr_page_alloc_for_ibuf(index, mtr));
}
- new_block = buf_page_get(dict_index_get_space(index),
- dict_table_zip_size(index->table),
- new_page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ new_block = btr_page_alloc_low(
+ index, hint_page_no, file_direction, level, mtr, init_mtr);
+
+ if (new_block) {
+ buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ }
return(new_block);
}
@@ -1087,10 +1120,10 @@ btr_page_free(
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
{
- ulint level;
-
- level = btr_page_get_level(buf_block_get_frame(block), mtr);
+ const page_t* page = buf_block_get_frame(block);
+ ulint level = btr_page_get_level(page, mtr);
+ ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX);
btr_page_free_low(index, block, level, mtr);
}
@@ -1329,16 +1362,12 @@ btr_create(
/* Allocate then the next page to the segment: it will be the
tree root page */
- page_no = fseg_alloc_free_page(buf_block_get_frame(
- ibuf_hdr_block)
- + IBUF_HEADER
- + IBUF_TREE_SEG_HEADER,
- IBUF_TREE_ROOT_PAGE_NO,
- FSP_UP, mtr);
- ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
-
- block = buf_page_get(space, zip_size, page_no,
- RW_X_LATCH, mtr);
+ block = fseg_alloc_free_page(
+ buf_block_get_frame(ibuf_hdr_block)
+ + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
+ IBUF_TREE_ROOT_PAGE_NO,
+ FSP_UP, mtr);
+ ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO);
} else {
#ifdef UNIV_BLOB_DEBUG
if ((type & DICT_CLUSTERED) && !index->blobs) {
@@ -1815,7 +1844,7 @@ btr_root_raise_and_insert(
level = btr_page_get_level(root, mtr);
- new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr);
+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
ut_a(!new_page_zip == !root_page_zip);
@@ -2551,7 +2580,7 @@ func_start:
/* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
- btr_page_get_level(page, mtr), mtr);
+ btr_page_get_level(page, mtr), mtr, mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index,
@@ -3001,15 +3030,16 @@ btr_node_ptr_delete(
ut_a(err == DB_SUCCESS);
if (!compressed) {
- btr_cur_compress_if_useful(&cursor, mtr);
+ btr_cur_compress_if_useful(&cursor, FALSE, mtr);
}
}
/*************************************************************//**
If page is the only on its level, this function moves its records to the
-father page, thus reducing the tree height. */
+father page, thus reducing the tree height.
+@return father block */
static
-void
+buf_block_t*
btr_lift_page_up(
/*=============*/
dict_index_t* index, /*!< in: index tree */
@@ -3126,6 +3156,8 @@ btr_lift_page_up(
}
ut_ad(page_validate(father_page, index));
ut_ad(btr_check_node_ptr(index, father_block, mtr));
+
+ return(father_block);
}
/*************************************************************//**
@@ -3142,11 +3174,13 @@ UNIV_INTERN
ibool
btr_compress(
/*=========*/
- btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
- the page must not be empty: in record delete
- use btr_discard_page if the page would become
- empty */
- mtr_t* mtr) /*!< in: mtr */
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
+ or lift; the page must not be empty:
+ when deleting records, use btr_discard_page()
+ if the page would become empty */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
dict_index_t* index;
ulint space;
@@ -3164,12 +3198,14 @@ btr_compress(
ulint* offsets;
ulint data_size;
ulint n_recs;
+ ulint nth_rec = 0; /* remove bogus warning */
ulint max_ins_size;
ulint max_ins_size_reorg;
block = btr_cur_get_block(cursor);
page = btr_cur_get_page(cursor);
index = btr_cur_get_index(cursor);
+
ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table));
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
@@ -3190,6 +3226,10 @@ btr_compress(
offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
&father_cursor);
+ if (adjust) {
+ nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
+ }
+
/* Decide the page to which we try to merge and which will inherit
the locks */
@@ -3216,9 +3256,9 @@ btr_compress(
} else {
/* The page is the only one on the level, lift the records
to the father */
- btr_lift_page_up(index, block, mtr);
- mem_heap_free(heap);
- return(TRUE);
+
+ merge_block = btr_lift_page_up(index, block, mtr);
+ goto func_exit;
}
n_recs = page_get_n_recs(page);
@@ -3300,6 +3340,10 @@ err_exit:
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
+
+ if (adjust) {
+ nth_rec += page_rec_get_n_recs_before(orig_pred);
+ }
} else {
rec_t* orig_succ;
#ifdef UNIV_BTR_DEBUG
@@ -3364,7 +3408,6 @@ err_exit:
}
btr_blob_dbg_remove(page, index, "btr_compress");
- mem_heap_free(heap);
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
/* Update the free bits of the B-tree page in the
@@ -3416,6 +3459,16 @@ err_exit:
btr_page_free(index, block, mtr);
ut_ad(btr_check_node_ptr(index, merge_block, mtr));
+func_exit:
+ mem_heap_free(heap);
+
+ if (adjust) {
+ btr_cur_position(
+ index,
+ page_rec_get_nth(merge_block->frame, nth_rec),
+ merge_block, cursor);
+ }
+
return(TRUE);
}
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index 9f4be053a43..b67da53ec8a 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,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
*****************************************************************************/
@@ -393,7 +393,12 @@ btr_cur_search_to_nth_level(
ut_ad(dict_index_check_search_tuple(index, tuple));
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside());
ut_ad(dtuple_check_typed(tuple));
+ ut_ad(index->page != FIL_NULL);
+ UNIV_MEM_INVALID(&cursor->up_match, sizeof cursor->up_match);
+ UNIV_MEM_INVALID(&cursor->up_bytes, sizeof cursor->up_bytes);
+ UNIV_MEM_INVALID(&cursor->low_match, sizeof cursor->low_match);
+ UNIV_MEM_INVALID(&cursor->low_bytes, sizeof cursor->low_bytes);
#ifdef UNIV_DEBUG
cursor->up_match = ULINT_UNDEFINED;
cursor->low_match = ULINT_UNDEFINED;
@@ -1752,7 +1757,7 @@ btr_cur_update_in_place(
page_zip = buf_block_get_page_zip(block);
/* Check that enough space is available on the compressed page. */
- if (UNIV_LIKELY_NULL(page_zip)
+ if (page_zip
&& !btr_cur_update_alloc_zip(page_zip, block, index,
rec_offs_size(offsets), FALSE, mtr)) {
return(DB_ZIP_OVERFLOW);
@@ -1943,7 +1948,7 @@ any_extern:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- if (UNIV_LIKELY_NULL(page_zip)
+ if (page_zip
&& !btr_cur_update_alloc_zip(page_zip, block, index,
new_rec_size, TRUE, mtr)) {
err = DB_ZIP_OVERFLOW;
@@ -2099,7 +2104,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback
flags */
- btr_cur_t* cursor, /*!< in: cursor on the record to update */
+ btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
+ cursor may become invalid if *big_rec == NULL
+ || !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */
@@ -2238,10 +2245,10 @@ btr_cur_pessimistic_update(
record to be inserted: we have to remember which fields were such */
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
- offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
+ ut_ad(rec_offs_validate(rec, index, offsets));
n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
ut_ad(page_is_comp(page));
if (page_zip_rec_needs_ext(
rec_get_converted_size(index, new_entry, n_ext),
@@ -2261,6 +2268,10 @@ make_external:
err = DB_TOO_BIG_RECORD;
goto return_after_reservations;
}
+
+ ut_ad(page_is_leaf(page));
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(flags & BTR_KEEP_POS_FLAG);
}
/* Store state of explicit locks on rec on the page infimum record,
@@ -2288,6 +2299,8 @@ make_external:
rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
if (rec) {
+ page_cursor->rec = rec;
+
lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
rec, block);
@@ -2301,7 +2314,10 @@ make_external:
rec, index, offsets, mtr);
}
- btr_cur_compress_if_useful(cursor, mtr);
+ btr_cur_compress_if_useful(
+ cursor,
+ big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG),
+ mtr);
if (page_zip && !dict_index_is_clust(index)
&& page_is_leaf(page)) {
@@ -2321,6 +2337,21 @@ make_external:
}
}
+ if (big_rec_vec) {
+ ut_ad(page_is_leaf(page));
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(flags & BTR_KEEP_POS_FLAG);
+
+ /* btr_page_split_and_insert() in
+ btr_cur_pessimistic_insert() invokes
+ mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
+ We must keep the index->lock when we created a
+ big_rec, so that row_upd_clust_rec() can store the
+ big_rec in the same mini-transaction. */
+
+ mtr_x_lock(dict_index_get_lock(index), mtr);
+ }
+
/* Was the record to be updated positioned as the first user
record on its page? */
was_first = page_cur_is_before_first(page_cursor);
@@ -2336,6 +2367,7 @@ make_external:
ut_a(rec);
ut_a(err == DB_SUCCESS);
ut_a(dummy_big_rec == NULL);
+ page_cursor->rec = rec;
if (dict_index_is_sec_or_ibuf(index)) {
/* Update PAGE_MAX_TRX_ID in the index page header.
@@ -2769,10 +2801,12 @@ UNIV_INTERN
ibool
btr_cur_compress_if_useful(
/*=======================*/
- btr_cur_t* cursor, /*!< in: cursor on the page to compress;
- cursor does not stay valid if compression
- occurs */
- mtr_t* mtr) /*!< in: mtr */
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
+ cursor does not stay valid if !adjust and
+ compression occurs */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ut_ad(mtr_memo_contains(mtr,
dict_index_get_lock(btr_cur_get_index(cursor)),
@@ -2781,7 +2815,7 @@ btr_cur_compress_if_useful(
MTR_MEMO_PAGE_X_FIX));
return(btr_cur_compress_recommendation(cursor, mtr)
- && btr_compress(cursor, mtr));
+ && btr_compress(cursor, adjust, mtr));
}
/*******************************************************//**
@@ -3023,7 +3057,7 @@ return_after_reservations:
mem_heap_free(heap);
if (ret == FALSE) {
- ret = btr_cur_compress_if_useful(cursor, mtr);
+ ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
}
if (n_extents > 0) {
@@ -3588,10 +3622,10 @@ btr_cur_set_ownership_of_extern_field(
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
}
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr);
- } else if (UNIV_LIKELY(mtr != NULL)) {
+ } else if (mtr != NULL) {
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
MLOG_1BYTE, mtr);
@@ -3823,9 +3857,9 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
-ulint
-btr_store_big_rec_extern_fields_func(
-/*=================================*/
+enum db_err
+btr_store_big_rec_extern_fields(
+/*============================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
@@ -3834,38 +3868,37 @@ btr_store_big_rec_extern_fields_func(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
-#ifdef UNIV_DEBUG
- mtr_t* local_mtr, /*!< in: mtr containing the
- latch to rec and to the tree */
-#endif /* UNIV_DEBUG */
-#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- ibool update_in_place,/*! in: TRUE if the record is updated
- in place (not delete+insert) */
-#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const big_rec_t*big_rec_vec) /*!< in: vector containing fields
+ const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
-
+ mtr_t* btr_mtr, /*!< in: mtr containing the
+ latches to the clustered index */
+ enum blob_op op) /*! in: operation code */
{
- ulint rec_page_no;
- byte* field_ref;
- ulint extern_len;
- ulint store_len;
- ulint page_no;
- ulint space_id;
- ulint zip_size;
- ulint prev_page_no;
- ulint hint_page_no;
- ulint i;
- mtr_t mtr;
- mem_heap_t* heap = NULL;
+ ulint rec_page_no;
+ byte* field_ref;
+ ulint extern_len;
+ ulint store_len;
+ ulint page_no;
+ ulint space_id;
+ ulint zip_size;
+ ulint prev_page_no;
+ ulint hint_page_no;
+ ulint i;
+ mtr_t mtr;
+ mtr_t* alloc_mtr;
+ mem_heap_t* heap = NULL;
page_zip_des_t* page_zip;
- z_stream c_stream;
+ z_stream c_stream;
+ buf_block_t** freed_pages = NULL;
+ ulint n_freed_pages = 0;
+ enum db_err error = DB_SUCCESS;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
- ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
+ ut_ad(btr_mtr);
+ ut_ad(mtr_memo_contains(btr_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains(btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
ut_a(dict_index_is_clust(index));
@@ -3878,7 +3911,7 @@ btr_store_big_rec_extern_fields_func(
rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
int err;
/* Zlib deflate needs 128 kilobytes for the default
@@ -3894,6 +3927,42 @@ btr_store_big_rec_extern_fields_func(
ut_a(err == Z_OK);
}
+ if (btr_blob_op_is_update(op)) {
+ /* Avoid reusing pages that have been previously freed
+ in btr_mtr. */
+ if (btr_mtr->n_freed_pages) {
+ if (heap == NULL) {
+ heap = mem_heap_create(
+ btr_mtr->n_freed_pages
+ * sizeof *freed_pages);
+ }
+
+ freed_pages = mem_heap_alloc(
+ heap,
+ btr_mtr->n_freed_pages
+ * sizeof *freed_pages);
+ n_freed_pages = 0;
+ }
+
+ /* Because btr_mtr will be committed after mtr, it is
+ possible that the tablespace has been extended when
+ the B-tree record was updated or inserted, or it will
+ be extended while allocating pages for big_rec.
+
+ TODO: In mtr (not btr_mtr), write a redo log record
+ about extending the tablespace to its current size,
+ and remember the current size. Whenever the tablespace
+ grows as pages are allocated, write further redo log
+ records to mtr. (Currently tablespace extension is not
+ covered by the redo log. If it were, the record would
+ only be written to btr_mtr, which is committed after
+ mtr.) */
+ alloc_mtr = btr_mtr;
+ } else {
+ /* Use the local mtr for allocations. */
+ alloc_mtr = &mtr;
+ }
+
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/* All pointers to externally stored columns in the record
must either be zero or they must be pointers to inherited
@@ -3908,7 +3977,7 @@ btr_store_big_rec_extern_fields_func(
/* Either this must be an update in place,
or the BLOB must be inherited, or the BLOB pointer
must be zero (will be written in this function). */
- ut_a(update_in_place
+ ut_a(op == BTR_STORE_UPDATE
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|| !memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE));
@@ -3933,7 +4002,7 @@ btr_store_big_rec_extern_fields_func(
prev_page_no = FIL_NULL;
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
int err = deflateReset(&c_stream);
ut_a(err == Z_OK);
@@ -3953,18 +4022,24 @@ btr_store_big_rec_extern_fields_func(
hint_page_no = prev_page_no + 1;
}
+alloc_another:
block = btr_page_alloc(index, hint_page_no,
- FSP_NO_DIR, 0, &mtr);
+ FSP_NO_DIR, 0, alloc_mtr, &mtr);
if (UNIV_UNLIKELY(block == NULL)) {
-
mtr_commit(&mtr);
+ error = DB_OUT_OF_FILE_SPACE;
+ goto func_exit;
+ }
- if (UNIV_LIKELY_NULL(page_zip)) {
- deflateEnd(&c_stream);
- mem_heap_free(heap);
- }
-
- return(DB_OUT_OF_FILE_SPACE);
+ if (rw_lock_get_x_lock_count(&block->lock) > 1) {
+ /* This page must have been freed in
+ btr_mtr previously. Put it aside, and
+ allocate another page for the BLOB data. */
+ ut_ad(alloc_mtr == btr_mtr);
+ ut_ad(btr_blob_op_is_update(op));
+ ut_ad(n_freed_pages < btr_mtr->n_freed_pages);
+ freed_pages[n_freed_pages++] = block;
+ goto alloc_another;
}
page_no = buf_block_get_page_no(block);
@@ -3981,7 +4056,7 @@ btr_store_big_rec_extern_fields_func(
SYNC_EXTERN_STORAGE);
prev_page = buf_block_get_frame(prev_block);
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
mlog_write_ulint(
prev_page + FIL_PAGE_NEXT,
page_no, MLOG_4BYTES, &mtr);
@@ -3998,7 +4073,7 @@ btr_store_big_rec_extern_fields_func(
}
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
int err;
page_zip_des_t* blob_page_zip;
@@ -4081,11 +4156,15 @@ btr_store_big_rec_extern_fields_func(
goto next_zip_page;
}
- rec_block = buf_page_get(space_id, zip_size,
- rec_page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(rec_block,
- SYNC_NO_ORDER_CHECK);
+ if (alloc_mtr == &mtr) {
+ rec_block = buf_page_get(
+ space_id, zip_size,
+ rec_page_no,
+ RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(
+ rec_block,
+ SYNC_NO_ORDER_CHECK);
+ }
if (err == Z_STREAM_END) {
mach_write_to_4(field_ref
@@ -4119,7 +4198,8 @@ btr_store_big_rec_extern_fields_func(
page_zip_write_blob_ptr(
page_zip, rec, index, offsets,
- big_rec_vec->fields[i].field_no, &mtr);
+ big_rec_vec->fields[i].field_no,
+ alloc_mtr);
next_zip_page:
prev_page_no = page_no;
@@ -4164,19 +4244,23 @@ next_zip_page:
extern_len -= store_len;
- rec_block = buf_page_get(space_id, zip_size,
- rec_page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(rec_block,
- SYNC_NO_ORDER_CHECK);
+ if (alloc_mtr == &mtr) {
+ rec_block = buf_page_get(
+ space_id, zip_size,
+ rec_page_no,
+ RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(
+ rec_block,
+ SYNC_NO_ORDER_CHECK);
+ }
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_LEN + 4,
big_rec_vec->fields[i].len
- extern_len,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
if (prev_page_no == FIL_NULL) {
btr_blob_dbg_add_blob(
@@ -4186,18 +4270,19 @@ next_zip_page:
mlog_write_ulint(field_ref
+ BTR_EXTERN_SPACE_ID,
- space_id,
- MLOG_4BYTES, &mtr);
+ space_id, MLOG_4BYTES,
+ alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_PAGE_NO,
- page_no,
- MLOG_4BYTES, &mtr);
+ page_no, MLOG_4BYTES,
+ alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_OFFSET,
FIL_PAGE_DATA,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES,
+ alloc_mtr);
}
prev_page_no = page_no;
@@ -4211,8 +4296,23 @@ next_zip_page:
}
}
- if (UNIV_LIKELY_NULL(page_zip)) {
+func_exit:
+ if (page_zip) {
deflateEnd(&c_stream);
+ }
+
+ if (n_freed_pages) {
+ ulint i;
+
+ ut_ad(alloc_mtr == btr_mtr);
+ ut_ad(btr_blob_op_is_update(op));
+
+ for (i = 0; i < n_freed_pages; i++) {
+ btr_page_free_low(index, freed_pages[i], 0, alloc_mtr);
+ }
+ }
+
+ if (heap != NULL) {
mem_heap_free(heap);
}
@@ -4233,7 +4333,7 @@ next_zip_page:
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- return(DB_SUCCESS);
+ return(error);
}
/*******************************************************************//**
@@ -4438,7 +4538,7 @@ btr_free_externally_stored_field(
btr_page_free_low(index, ext_block, 0, &mtr);
- if (UNIV_LIKELY(page_zip != NULL)) {
+ if (page_zip) {
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
next_page_no);
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
index d88860b807b..c2000d67303 100644
--- a/storage/innodb_plugin/buf/buf0buf.c
+++ b/storage/innodb_plugin/buf/buf0buf.c
@@ -750,11 +750,8 @@ buf_chunk_init(
for (i = chunk->size; i--; ) {
buf_block_init(block, frame);
+ UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
-#ifdef HAVE_purify
- /* Wipe contents of frame to eliminate a Purify warning */
- memset(block->frame, '\0', UNIV_PAGE_SIZE);
-#endif
/* Add the block to the free list */
UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
ut_d(block->page.in_free_list = TRUE);
@@ -2151,7 +2148,7 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- ut_a(block->page.file_page_was_freed == FALSE);
+ ut_a(mode == BUF_KEEP_OLD || !block->page.file_page_was_freed);
#endif
#ifdef UNIV_IBUF_COUNT_DEBUG
diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
index 0f774dcaaa1..01057c26d94 100644
--- a/storage/innodb_plugin/fil/fil0fil.c
+++ b/storage/innodb_plugin/fil/fil0fil.c
@@ -918,11 +918,6 @@ retry:
return;
}
- if (fil_system->n_open < fil_system->max_n_open) {
-
- return;
- }
-
space = fil_space_get_by_id(space_id);
if (space != NULL && space->stop_ios) {
@@ -939,6 +934,25 @@ retry:
mutex_exit(&fil_system->mutex);
+#ifndef UNIV_HOTBACKUP
+
+ /* Wake the i/o-handler threads to make sure pending
+ i/o's are performed */
+ os_aio_simulated_wake_handler_threads();
+
+ /* The sleep here is just to give IO helper threads a
+ bit of time to do some work. It is not required that
+ all IO related to the tablespace being renamed must
+ be flushed here as we do fil_flush() in
+ fil_rename_tablespace() as well. */
+ os_thread_sleep(20000);
+
+#endif /* UNIV_HOTBACKUP */
+
+ /* Flush tablespaces so that we can close modified
+ files in the LRU list */
+ fil_flush_file_spaces(FIL_TABLESPACE);
+
os_thread_sleep(20000);
count2++;
@@ -946,6 +960,11 @@ retry:
goto retry;
}
+ if (fil_system->n_open < fil_system->max_n_open) {
+
+ return;
+ }
+
/* If the file is already open, no need to do anything; if the space
does not exist, we handle the situation in the function which called
this function */
@@ -2496,7 +2515,7 @@ fil_rename_tablespace(
retry:
count++;
- if (count > 1000) {
+ if (!(count % 1000)) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: problems renaming ", stderr);
ut_print_filename(stderr, old_name);
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index fee7fde2e5c..c84cae302a6 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/fsp/fsp0fsp.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, 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
*****************************************************************************/
@@ -312,28 +312,38 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page;
then we do not allocate more extents */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr); /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return the allocated page number, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
-ulint
+buf_block_t*
fseg_alloc_free_page_low(
/*=====================*/
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
+ __attribute__((warn_unused_result, nonnull));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -701,17 +711,18 @@ list, if not free limit == space size. This adding is necessary to make the
descriptor defined, as they are uninitialized above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-UNIV_INLINE
+UNIV_INLINE __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor_with_space_hdr(
/*===============================*/
- fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
- ulint space, /*!< in: space id */
- ulint offset, /*!< in: page offset;
- if equal to the free limit,
- we try to add new extents to
- the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ fsp_header_t* sp_header, /*!< in/out: space header, x-latched
+ in mtr */
+ ulint space, /*!< in: space id */
+ ulint offset, /*!< in: page offset; if equal
+ to the free limit, we try to
+ add new extents to the space
+ free list */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -719,11 +730,9 @@ xdes_get_descriptor_with_space_hdr(
ulint descr_page_no;
page_t* descr_page;
- ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
- || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
/* Read free limit and space size */
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
@@ -773,7 +782,7 @@ is necessary to make the descriptor defined, as they are uninitialized
above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-static
+static __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor(
/*================*/
@@ -782,7 +791,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */
ulint offset, /*!< in: page offset; if equal to the free limit,
we try to add new extents to the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fsp_header_t* sp_header;
@@ -1160,14 +1169,14 @@ fsp_header_get_tablespace_size(void)
Tries to extend a single-table tablespace so that a page would fit in the
data file.
@return TRUE if success */
-static
+static __attribute__((nonnull, warn_unused_result))
ibool
fsp_try_extend_data_file_with_pages(
/*================================*/
ulint space, /*!< in: space */
ulint page_no, /*!< in: page number */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ibool success;
ulint actual_size;
@@ -1192,7 +1201,7 @@ fsp_try_extend_data_file_with_pages(
/***********************************************************************//**
Tries to extend the last data file of a tablespace if it is auto-extending.
@return FALSE if not auto-extending */
-static
+static __attribute__((nonnull))
ibool
fsp_try_extend_data_file(
/*=====================*/
@@ -1202,8 +1211,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to
megabyte */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint size;
ulint zip_size;
@@ -1339,7 +1348,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -1538,29 +1547,120 @@ fsp_alloc_free_extent(
}
/**********************************************************************//**
-Allocates a single free page from a space. The page is marked as used.
-@return the page offset, FIL_NULL if no page could be allocated */
+Allocates a single free page from a space. */
+static __attribute__((nonnull))
+void
+fsp_alloc_from_free_frag(
+/*=====================*/
+ fsp_header_t* header, /*!< in/out: tablespace header */
+ xdes_t* descr, /*!< in/out: extent descriptor */
+ ulint bit, /*!< in: slot to allocate in the extent */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ ulint frag_n_used;
+
+ ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
+ ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
+ xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
+
+ /* Update the FRAG_N_USED field */
+ frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
+ mtr);
+ frag_n_used++;
+ mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
+ mtr);
+ if (xdes_is_full(descr, mtr)) {
+ /* The fragment is full: move it to another list */
+ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ xdes_set_state(descr, XDES_FULL_FRAG, mtr);
+
+ flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ mlog_write_ulint(header + FSP_FRAG_N_USED,
+ frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
+ mtr);
+ }
+}
+
+/**********************************************************************//**
+Gets a buffer block for an allocated page.
+
+NOTE: If init_mtr != mtr, the block will only be initialized if it was
+not previously x-latched. It is assumed that the block has been
+x-latched only by mtr, and freed in mtr in that case.
+
+@return block, initialized if init_mtr==mtr
+or rw_lock_x_lock_count(&block->lock) == 1 */
static
-ulint
+buf_block_t*
+fsp_page_create(
+/*============*/
+ ulint space, /*!< in: space id of the allocated page */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number of the allocated page */
+ mtr_t* mtr, /*!< in: mini-transaction of the allocation */
+ mtr_t* init_mtr) /*!< in: mini-transaction for initializing
+ the page */
+{
+ buf_block_t* block
+ = buf_page_create(space, page_no, zip_size, init_mtr);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
+ == rw_lock_own(&block->lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */
+ rw_lock_x_lock(&block->lock);
+ mutex_enter(&block->mutex);
+ buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+ mutex_exit(&block->mutex);
+ mtr_memo_push(init_mtr, block, MTR_MEMO_PAGE_X_FIX);
+
+ if (init_mtr == mtr
+ || rw_lock_get_x_lock_count(&block->lock) == 1) {
+
+ /* Initialize the page, unless it was already
+ X-latched in mtr. (In this case, we would want to
+ allocate another page that has not been freed in mtr.) */
+ ut_ad(init_mtr == mtr
+ || !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+
+ fsp_init_file_page(block, init_mtr);
+ }
+
+ return(block);
+}
+
+/**********************************************************************//**
+Allocates a single free page from a space. The page is marked as used.
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+static __attribute__((nonnull, warn_unused_result))
+buf_block_t*
fsp_alloc_free_page(
/*================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint hint, /*!< in: hint of which page would be desirable */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
+ page should be initialized
+ (may be the same as mtr) */
{
fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
- buf_block_t* block;
ulint free;
- ulint frag_n_used;
ulint page_no;
ulint space_size;
- ibool success;
ut_ad(mtr);
+ ut_ad(init_mtr);
header = fsp_get_space_header(space, zip_size, mtr);
@@ -1587,7 +1687,7 @@ fsp_alloc_free_page(
if (descr == NULL) {
/* No free space left */
- return(FIL_NULL);
+ return(NULL);
}
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
@@ -1632,50 +1732,18 @@ fsp_alloc_free_page(
" space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size,
(ulong) page_no);
- return(FIL_NULL);
+ return(NULL);
}
- success = fsp_try_extend_data_file_with_pages(space, page_no,
- header, mtr);
- if (!success) {
+ if (!fsp_try_extend_data_file_with_pages(space, page_no,
+ header, mtr)) {
/* No disk space left */
- return(FIL_NULL);
+ return(NULL);
}
}
- xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
+ fsp_alloc_from_free_frag(header, descr, free, mtr);
- /* Update the FRAG_N_USED field */
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
- mtr);
- frag_n_used++;
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
- mtr);
- if (xdes_is_full(descr, mtr)) {
- /* The fragment is full: move it to another list */
- flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
- xdes_set_state(descr, XDES_FULL_FRAG, mtr);
-
- flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
- mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
- mtr);
- }
-
- /* Initialize the allocated page to the buffer pool, so that it can
- be obtained immediately with buf_page_get without need for a disk
- read. */
-
- buf_page_create(space, page_no, zip_size, mtr);
-
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- /* Prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
-
- return(page_no);
+ return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
}
/**********************************************************************//**
@@ -1714,6 +1782,9 @@ fsp_free_page(
fputs("InnoDB: Dump of descriptor: ", stderr);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
+ /* Crash in debug version, so that we get a core dump
+ of this corruption. */
+ ut_ad(0);
if (state == XDES_FREE) {
/* We put here some fault tolerance: if the page
@@ -1732,6 +1803,9 @@ fsp_free_page(
"InnoDB: Dump of descriptor: ", (ulong) page);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
+ /* Crash in debug version, so that we get a core dump
+ of this corruption. */
+ ut_ad(0);
/* We put here some fault tolerance: if the page
is already free, return without doing anything! */
@@ -1766,6 +1840,8 @@ fsp_free_page(
mtr);
fsp_free_extent(space, zip_size, page, mtr);
}
+
+ mtr->n_freed_pages++;
}
/**********************************************************************//**
@@ -1898,7 +1974,6 @@ fsp_alloc_seg_inode_page(
fseg_inode_t* inode;
buf_block_t* block;
page_t* page;
- ulint page_no;
ulint space;
ulint zip_size;
ulint i;
@@ -1909,15 +1984,15 @@ fsp_alloc_seg_inode_page(
zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
- page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
+ block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
- if (page_no == FIL_NULL) {
+ if (block == NULL) {
return(FALSE);
}
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
block->check_index_page_at_flush = FALSE;
@@ -2322,19 +2397,20 @@ fseg_create_general(
}
if (page == 0) {
- page = fseg_alloc_free_page_low(space, zip_size,
- inode, 0, FSP_UP, mtr);
+ block = fseg_alloc_free_page_low(space, zip_size,
+ inode, 0, FSP_UP, mtr, mtr);
- if (page == FIL_NULL) {
+ if (block == NULL) {
fsp_free_seg_inode(space, zip_size, inode, mtr);
goto funct_exit;
}
- block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
+
header = byte_offset + buf_block_get_frame(block);
- mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
+ mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
}
@@ -2511,8 +2587,10 @@ fseg_fill_free_list(
Allocates a free extent for the segment: looks first in the free list of the
segment, then tries to allocate from the space free list. NOTE that the extent
returned still resides in the segment free list, it is not yet taken off it!
-@return allocated extent, still placed in the segment free list, NULL
-if could not be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
xdes_t*
fseg_alloc_free_extent(
@@ -2564,22 +2642,30 @@ fseg_alloc_free_extent(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return the allocated page number, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
-ulint
+buf_block_t*
fseg_alloc_free_page_low(
/*=====================*/
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
{
fsp_header_t* space_header;
ulint space_size;
@@ -2590,7 +2676,6 @@ fseg_alloc_free_page_low(
ulint ret_page; /*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t* ret_descr; /*!< the extent of the allocated page */
- ibool frag_page_allocated = FALSE;
ibool success;
ulint n;
@@ -2612,6 +2697,7 @@ fseg_alloc_free_page_low(
if (descr == NULL) {
/* Hint outside space or too high above free limit: reset
hint */
+ /* The file space header page is always allocated. */
hint = 0;
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
}
@@ -2623,15 +2709,19 @@ fseg_alloc_free_page_low(
mtr), seg_id))
&& (xdes_get_bit(descr, XDES_FREE_BIT,
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
-
+take_hinted_page:
/* 1. We can take the hinted page
=================================*/
ret_descr = descr;
ret_page = hint;
+ /* Skip the check for extending the tablespace. If the
+ page hint were not within the size of the tablespace,
+ we would have got (descr == NULL) above and reset the hint. */
+ goto got_hinted_page;
/*-----------------------------------------------------------*/
- } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
- && ((reserved - used) < reserved / FSEG_FILLFACTOR)
- && (used >= FSEG_FRAG_LIMIT)) {
+ } else if (xdes_get_state(descr, mtr) == XDES_FREE
+ && reserved - used < reserved / FSEG_FILLFACTOR
+ && used >= FSEG_FRAG_LIMIT) {
/* 2. We allocate the free extent from space and can take
=========================================================
@@ -2649,7 +2739,7 @@ fseg_alloc_free_page_low(
/* Try to fill the segment free list */
fseg_fill_free_list(seg_inode, space, zip_size,
hint + FSP_EXTENT_SIZE, mtr);
- ret_page = hint;
+ goto take_hinted_page;
/*-----------------------------------------------------------*/
} else if ((direction != FSP_NO_DIR)
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
@@ -2698,7 +2788,7 @@ fseg_alloc_free_page_low(
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
} else {
ut_error;
- return(FIL_NULL);
+ return(NULL);
}
ret_descr = xdes_lst_get_descriptor(space, zip_size,
@@ -2710,20 +2800,23 @@ fseg_alloc_free_page_low(
} else if (used < FSEG_FRAG_LIMIT) {
/* 6. We allocate an individual page from the space
===================================================*/
- ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
- ret_descr = NULL;
-
- frag_page_allocated = TRUE;
+ buf_block_t* block = fsp_alloc_free_page(
+ space, zip_size, hint, mtr, init_mtr);
- if (ret_page != FIL_NULL) {
+ if (block != NULL) {
/* Put the page in the fragment page array of the
segment */
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
- ut_a(n != FIL_NULL);
+ ut_a(n != ULINT_UNDEFINED);
- fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
- mtr);
+ fseg_set_nth_frag_page_no(
+ seg_inode, n, buf_block_get_page_no(block),
+ mtr);
}
+
+ /* fsp_alloc_free_page() invoked fsp_init_file_page()
+ already. */
+ return(block);
/*-----------------------------------------------------------*/
} else {
/* 7. We allocate a new extent and take its first page
@@ -2741,7 +2834,7 @@ fseg_alloc_free_page_low(
if (ret_page == FIL_NULL) {
/* Page could not be allocated */
- return(FIL_NULL);
+ return(NULL);
}
if (space != 0) {
@@ -2759,38 +2852,22 @@ fseg_alloc_free_page_low(
" the space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size,
(ulong) ret_page);
- return(FIL_NULL);
+ return(NULL);
}
success = fsp_try_extend_data_file_with_pages(
space, ret_page, space_header, mtr);
if (!success) {
/* No disk space left */
- return(FIL_NULL);
+ return(NULL);
}
}
}
- if (!frag_page_allocated) {
- /* Initialize the allocated page to buffer pool, so that it
- can be obtained immediately with buf_page_get without need
- for a disk read */
- buf_block_t* block;
- ulint zip_size = dict_table_flags_to_zip_size(
- mach_read_from_4(FSP_SPACE_FLAGS + space_header));
-
- block = buf_page_create(space, ret_page, zip_size, mtr);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
- ret_page, RW_X_LATCH,
- mtr))) {
- ut_error;
- }
-
- /* The prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
-
+got_hinted_page:
+ /* ret_descr == NULL if the block was allocated from free_frag
+ (XDES_FREE_FRAG) */
+ if (ret_descr != NULL) {
/* At this point we know the extent and the page offset.
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
@@ -2803,20 +2880,28 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
}
- return(ret_page);
+ return(fsp_page_create(
+ space, dict_table_flags_to_zip_size(
+ mach_read_from_4(FSP_SPACE_FLAGS
+ + space_header)),
+ ret_page, mtr, init_mtr));
}
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
-ulint
+buf_block_t*
fseg_alloc_free_page_general(
/*=========================*/
fseg_header_t* seg_header,/*!< in/out: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
@@ -2827,15 +2912,18 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction handle */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
{
fseg_inode_t* inode;
ulint space;
ulint flags;
ulint zip_size;
rw_lock_t* latch;
- ibool success;
- ulint page_no;
+ buf_block_t* block;
ulint n_reserved;
space = page_get_space_id(page_align(seg_header));
@@ -2860,43 +2948,20 @@ fseg_alloc_free_page_general(
inode = fseg_inode_get(seg_header, space, zip_size, mtr);
- if (!has_done_reservation) {
- success = fsp_reserve_free_extents(&n_reserved, space, 2,
- FSP_NORMAL, mtr);
- if (!success) {
- return(FIL_NULL);
- }
+ if (!has_done_reservation
+ && !fsp_reserve_free_extents(&n_reserved, space, 2,
+ FSP_NORMAL, mtr)) {
+ return(NULL);
}
- page_no = fseg_alloc_free_page_low(space, zip_size,
- inode, hint, direction, mtr);
+ block = fseg_alloc_free_page_low(space, zip_size,
+ inode, hint, direction,
+ mtr, init_mtr);
if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved);
}
- return(page_no);
-}
-
-/**********************************************************************//**
-Allocates a single free page from a segment. This function implements
-the intelligent allocation strategy which tries to minimize file space
-fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header,/*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction,/*!< in: if the new page is needed because
- of an index page split, and records are
- inserted there in order, into which
- direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
-{
- return(fseg_alloc_free_page_general(seg_header, hint, direction,
- FALSE, mtr));
+ return(block);
}
/**********************************************************************//**
@@ -3412,6 +3477,8 @@ crash:
descr + XDES_FLST_NODE, mtr);
fsp_free_extent(space, zip_size, page, mtr);
}
+
+ mtr->n_freed_pages++;
}
/**********************************************************************//**
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index bb47bd24867..0edbf30cd0d 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -26,8 +26,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
*****************************************************************************/
@@ -1039,6 +1039,20 @@ innobase_get_charset(
}
/**********************************************************************//**
+Get the current setting of the lower_case_table_names global parameter from
+mysqld.cc. We do a dirty read because for one there is no synchronization
+object and secondly there is little harm in doing so even if we get a torn
+read.
+@return value of lower_case_table_names */
+ulint
+innobase_get_lower_case_table_names(void)
+/*=====================================*/
+{
+ return(lower_case_table_names);
+}
+
+
+/**********************************************************************//**
Determines the current SQL statement.
@return SQL statement string */
extern "C" UNIV_INTERN
@@ -3008,52 +3022,140 @@ ha_innobase::primary_key_is_clustered()
return(true);
}
+/** Always normalize table name to lower case on Windows */
+#ifdef __WIN__
+#define normalize_table_name(norm_name, name) \
+ normalize_table_name_low(norm_name, name, TRUE)
+#else
+#define normalize_table_name(norm_name, name) \
+ normalize_table_name_low(norm_name, name, FALSE)
+#endif /* __WIN__ */
+
/*****************************************************************//**
Normalizes a table name string. A normalized name consists of the
database name catenated to '/' and table name. An example:
test/mytable. On Windows normalization puts both the database name and the
-table name always to lower case. */
+table name always to lower case if "set_lower_case" is set to TRUE. */
static
void
-normalize_table_name(
-/*=================*/
+normalize_table_name_low(
+/*=====================*/
char* norm_name, /*!< out: normalized name as a
null-terminated string */
- const char* name) /*!< in: table name string */
+ const char* name, /*!< in: table name string */
+ ibool set_lower_case) /*!< in: TRUE if we want to set
+ name to lower case */
{
char* name_ptr;
char* db_ptr;
+ ulint db_len;
char* ptr;
/* Scan name from the end */
- ptr = strend(name)-1;
+ ptr = strend(name) - 1;
+ /* seek to the last path separator */
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--;
}
name_ptr = ptr + 1;
- DBUG_ASSERT(ptr > name);
+ /* skip any number of path separators */
+ while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
+ ptr--;
+ }
- ptr--;
+ DBUG_ASSERT(ptr >= name);
+ /* seek to the last but one path separator or one char before
+ the beginning of name */
+ db_len = 0;
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--;
+ db_len++;
}
db_ptr = ptr + 1;
- memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
+ memcpy(norm_name, db_ptr, db_len);
- norm_name[name_ptr - db_ptr - 1] = '/';
+ norm_name[db_len] = '/';
-#ifdef __WIN__
- innobase_casedn_str(norm_name);
-#endif
+ memcpy(norm_name + db_len + 1, name_ptr, strlen(name_ptr) + 1);
+
+ if (set_lower_case) {
+ innobase_casedn_str(norm_name);
+ }
}
+#if !defined(DBUG_OFF)
+/*********************************************************************
+Test normalize_table_name_low(). */
+static
+void
+test_normalize_table_name_low()
+/*===========================*/
+{
+ char norm_name[128];
+ const char* test_data[][2] = {
+ /* input, expected result */
+ {"./mysqltest/t1", "mysqltest/t1"},
+ {"./test/#sql-842b_2", "test/#sql-842b_2"},
+ {"./test/#sql-85a3_10", "test/#sql-85a3_10"},
+ {"./test/#sql2-842b-2", "test/#sql2-842b-2"},
+ {"./test/bug29807", "test/bug29807"},
+ {"./test/foo", "test/foo"},
+ {"./test/innodb_bug52663", "test/innodb_bug52663"},
+ {"./test/t", "test/t"},
+ {"./test/t1", "test/t1"},
+ {"./test/t10", "test/t10"},
+ {"/a/b/db/table", "db/table"},
+ {"/a/b/db///////table", "db/table"},
+ {"/a/b////db///////table", "db/table"},
+ {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
+ {"db/table", "db/table"},
+ {"ddd/t", "ddd/t"},
+ {"d/ttt", "d/ttt"},
+ {"d/t", "d/t"},
+ {".\\mysqltest\\t1", "mysqltest/t1"},
+ {".\\test\\#sql-842b_2", "test/#sql-842b_2"},
+ {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
+ {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
+ {".\\test\\bug29807", "test/bug29807"},
+ {".\\test\\foo", "test/foo"},
+ {".\\test\\innodb_bug52663", "test/innodb_bug52663"},
+ {".\\test\\t", "test/t"},
+ {".\\test\\t1", "test/t1"},
+ {".\\test\\t10", "test/t10"},
+ {"C:\\a\\b\\db\\table", "db/table"},
+ {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
+ {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
+ {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
+ {"db\\table", "db/table"},
+ {"ddd\\t", "ddd/t"},
+ {"d\\ttt", "d/ttt"},
+ {"d\\t", "d/t"},
+ };
+
+ for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
+ printf("test_normalize_table_name_low(): "
+ "testing \"%s\", expected \"%s\"... ",
+ test_data[i][0], test_data[i][1]);
+
+ normalize_table_name_low(norm_name, test_data[i][0], FALSE);
+
+ if (strcmp(norm_name, test_data[i][1]) == 0) {
+ printf("ok\n");
+ } else {
+ printf("got \"%s\"\n", norm_name);
+ ut_error;
+ }
+ }
+}
+#endif /* !DBUG_OFF */
+
/********************************************************************//**
Get the upper limit of the MySQL integral and floating-point type.
@return maximum allowed value for the field */
@@ -3445,6 +3547,8 @@ ha_innobase::open(
THD* thd;
ulint retries = 0;
char* is_part = NULL;
+ ibool par_case_name_set = FALSE;
+ char par_case_name[MAX_FULL_NAME_LEN + 1];
DBUG_ENTER("ha_innobase::open");
@@ -3491,16 +3595,87 @@ ha_innobase::open(
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. */
+#ifdef __WIN__
+ is_part = strstr(norm_name, "#p#");
+#else
is_part = strstr(norm_name, "#P#");
+#endif /* __WIN__ */
+
retry:
/* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get(norm_name, TRUE);
-
+
if (NULL == ib_table) {
if (is_part && retries < 10) {
- ++retries;
- os_thread_sleep(100000);
- goto retry;
+ /* 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
+ for sub-partition names as well. InnoDB always
+ normalises file names to lower case on Windows, this
+ can potentially cause problems when copying/moving
+ tables between platforms.
+
+ 1) If boot against an installation from Windows
+ platform, then its partition table name could
+ be all be in lower case in system tables. So we
+ will need to check lower case name when load table.
+
+ 2) If we boot an installation from other case
+ sensitive platform in Windows, we might need to
+ check the existence of table name without lowering
+ case them in the system table. */
+ if (innobase_get_lower_case_table_names() == 1) {
+
+ if (!par_case_name_set) {
+#ifndef __WIN__
+ /* Check for the table using lower
+ case name, including the partition
+ separator "P" */
+ memcpy(par_case_name, norm_name,
+ strlen(norm_name));
+ par_case_name[strlen(norm_name)] = 0;
+ innobase_casedn_str(par_case_name);
+#else
+ /* On Windows platfrom, check
+ whether there exists table name in
+ system table whose name is
+ not being normalized to lower case */
+ normalize_table_name_low(
+ par_case_name, name, FALSE);
+#endif
+ par_case_name_set = TRUE;
+ }
+
+ ib_table = dict_table_get(
+ par_case_name, FALSE);
+ }
+ if (!ib_table) {
+ ++retries;
+ os_thread_sleep(100000);
+ goto retry;
+ } else {
+#ifndef __WIN__
+ sql_print_warning("Partition table %s opened "
+ "after converting to lower "
+ "case. The table may have "
+ "been moved from a case "
+ "in-sensitive file system. "
+ "Please recreate table in "
+ "the current file system\n",
+ norm_name);
+#else
+ sql_print_warning("Partition table %s opened "
+ "after skipping the step to "
+ "lower case the table name. "
+ "The table may have been "
+ "moved from a case sensitive "
+ "file system. Please "
+ "recreate table in the "
+ "current file system\n",
+ norm_name);
+#endif
+ goto table_opened;
+ }
}
if (is_part) {
@@ -3531,6 +3706,8 @@ retry:
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
+table_opened:
+
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
sql_print_error("MySQL is trying to open a table handle but "
"the .ibd file for\ntable %s does not exist.\n"
@@ -6948,6 +7125,11 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ DBUG_EXECUTE_IF(
+ "test_normalize_table_name_low",
+ test_normalize_table_name_low();
+ );
+
/* Strangely, MySQL passes the table name without the '.frm'
extension, in contrast to ::create */
normalize_table_name(norm_name, name);
@@ -11034,6 +11216,13 @@ static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
"trigger a readahead.",
NULL, NULL, 56, 0, 64, 0);
+#ifdef UNIV_DEBUG
+static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
+ PLUGIN_VAR_RQCMDARG,
+ "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
+ NULL, NULL, 0, 0, 1024, 0);
+#endif /* UNIV_DEBUG */
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
@@ -11095,6 +11284,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(random_read_ahead),
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
+#ifdef UNIV_DEBUG
+ MYSQL_SYSVAR(trx_rseg_n_slots_debug),
+#endif /* UNIV_DEBUG */
NULL
};
diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
index a22de3b0e70..f2b51c7ebed 100644
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2012, 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
*****************************************************************************/
@@ -1722,14 +1722,14 @@ ulint
ibuf_add_free_page(void)
/*====================*/
{
- mtr_t mtr;
- page_t* header_page;
- ulint flags;
- ulint zip_size;
- ulint page_no;
- page_t* page;
- page_t* root;
- page_t* bitmap_page;
+ mtr_t mtr;
+ page_t* header_page;
+ ulint flags;
+ ulint zip_size;
+ buf_block_t* block;
+ page_t* page;
+ page_t* root;
+ page_t* bitmap_page;
mtr_start(&mtr);
@@ -1750,32 +1750,23 @@ ibuf_add_free_page(void)
of a deadlock. This is the reason why we created a special ibuf
header page apart from the ibuf tree. */
- page_no = fseg_alloc_free_page(
+ block = fseg_alloc_free_page(
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
&mtr);
- if (page_no == FIL_NULL) {
+ if (block == NULL) {
mtr_commit(&mtr);
return(DB_STRONG_FAIL);
}
- {
- buf_block_t* block;
-
- block = buf_page_get(
- IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
-
- ibuf_enter();
-
- mutex_enter(&ibuf_mutex);
-
- root = ibuf_tree_root_get(&mtr);
-
- buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
+ ibuf_enter();
+ mutex_enter(&ibuf_mutex);
+ root = ibuf_tree_root_get(&mtr);
- page = buf_block_get_frame(block);
- }
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
+ page = buf_block_get_frame(block);
/* Add the page to the free list and update the ibuf size data */
@@ -1792,10 +1783,11 @@ ibuf_add_free_page(void)
(level 2 page) */
bitmap_page = ibuf_bitmap_get_map_page(
- IBUF_SPACE_ID, page_no, zip_size, &mtr);
+ IBUF_SPACE_ID, buf_block_get_page_no(block), zip_size, &mtr);
ibuf_bitmap_page_set_bits(
- bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
+ bitmap_page, buf_block_get_page_no(block), zip_size,
+ IBUF_BITMAP_IBUF, TRUE, &mtr);
mtr_commit(&mtr);
@@ -2090,7 +2082,15 @@ ibuf_get_merge_page_nos(
} else {
rec_page_no = ibuf_rec_get_page_no(rec);
rec_space_id = ibuf_rec_get_space(rec);
- ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
+ /* In the system tablespace, the smallest
+ possible secondary index leaf page number is
+ bigger than IBUF_TREE_ROOT_PAGE_NO (4). In
+ other tablespaces, the clustered index tree is
+ created at page 3, which makes page 4 the
+ smallest possible secondary index leaf page
+ (and that only after DROP INDEX). */
+ ut_ad(rec_page_no
+ > IBUF_TREE_ROOT_PAGE_NO - (rec_space_id != 0));
}
#ifdef UNIV_IBUF_DEBUG
diff --git a/storage/innodb_plugin/include/btr0btr.h b/storage/innodb_plugin/include/btr0btr.h
index e32da9e4c86..6e7bb8fc61e 100644
--- a/storage/innodb_plugin/include/btr0btr.h
+++ b/storage/innodb_plugin/include/btr0btr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -488,11 +488,14 @@ UNIV_INTERN
ibool
btr_compress(
/*=========*/
- btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
- the page must not be empty: in record delete
- use btr_discard_page if the page would become
- empty */
- mtr_t* mtr); /*!< in: mtr */
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
+ or lift; the page must not be empty:
+ when deleting records, use btr_discard_page()
+ if the page would become empty */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/*************************************************************//**
Discards a page from a B-tree. This is used to remove the last record from
a B-tree page: the whole page must be removed at the same time. This cannot
@@ -543,7 +546,10 @@ btr_get_size(
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
-@return new allocated block, x-latched; NULL if out of space */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
buf_block_t*
btr_page_alloc(
@@ -554,7 +560,12 @@ btr_page_alloc(
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
- mtr_t* mtr); /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ for x-latching and initializing
+ the page */
+ __attribute__((nonnull, warn_unused_result));
/**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
diff --git a/storage/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h
index 3669ce28f02..afc111970e2 100644
--- a/storage/innodb_plugin/include/btr0cur.h
+++ b/storage/innodb_plugin/include/btr0cur.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
update vector or inserted entry */
+#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update()
+ must keep cursor position when
+ moving columns to big_rec */
#ifndef UNIV_HOTBACKUP
#include "que0types.h"
@@ -309,7 +312,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback
flags */
- btr_cur_t* cursor, /*!< in: cursor on the record to update */
+ btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
+ cursor may become invalid if *big_rec == NULL
+ || !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */
@@ -376,10 +381,13 @@ UNIV_INTERN
ibool
btr_cur_compress_if_useful(
/*=======================*/
- btr_cur_t* cursor, /*!< in: cursor on the page to compress;
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
cursor does not stay valid if compression
occurs */
- mtr_t* mtr); /*!< in: mtr */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/*******************************************************//**
Removes the record on which the tree cursor is positioned. It is assumed
that the mtr has an x-latch on the page where the cursor is positioned,
@@ -504,6 +512,27 @@ btr_cur_disown_inherited_fields(
const upd_t* update, /*!< in: update vector */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull(2,3,4,5,6)));
+
+/** Operation code for btr_store_big_rec_extern_fields(). */
+enum blob_op {
+ /** Store off-page columns for a freshly inserted record */
+ BTR_STORE_INSERT = 0,
+ /** Store off-page columns for an insert by update */
+ BTR_STORE_INSERT_UPDATE,
+ /** Store off-page columns for an update */
+ BTR_STORE_UPDATE
+};
+
+/*******************************************************************//**
+Determine if an operation on off-page columns is an update.
+@return TRUE if op != BTR_STORE_INSERT */
+UNIV_INLINE
+ibool
+btr_blob_op_is_update(
+/*==================*/
+ enum blob_op op) /*!< in: operation */
+ __attribute__((warn_unused_result));
+
/*******************************************************************//**
Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
@@ -511,52 +540,23 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
-ulint
-btr_store_big_rec_extern_fields_func(
-/*=================================*/
+enum db_err
+btr_store_big_rec_extern_fields(
+/*============================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
- rec_t* rec, /*!< in: record */
+ rec_t* rec, /*!< in/out: record */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
-#ifdef UNIV_DEBUG
- mtr_t* local_mtr, /*!< in: mtr containing the
- latch to rec and to the tree */
-#endif /* UNIV_DEBUG */
-#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- ibool update_in_place,/*! in: TRUE if the record is updated
- in place (not delete+insert) */
-#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const big_rec_t*big_rec_vec) /*!< in: vector containing fields
+ const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
- __attribute__((nonnull));
-
-/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
-them in rec. The extern flags in rec will have to be set beforehand.
-The fields are stored on pages allocated from leaf node
-file segment of the index tree.
-@param index in: clustered index; MUST be X-latched by mtr
-@param b in/out: block containing rec; MUST be X-latched by mtr
-@param rec in/out: clustered index record
-@param offsets in: rec_get_offsets(rec, index);
- the "external storage" flags in offsets will not be adjusted
-@param mtr in: mini-transaction that holds x-latch on index and b
-@param upd in: TRUE if the record is updated in place (not delete+insert)
-@param big in: vector containing fields to be stored externally
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-#ifdef UNIV_DEBUG
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
-#elif defined UNIV_BLOB_LIGHT_DEBUG
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
-#else
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
-#endif
+ mtr_t* btr_mtr, /*!< in: mtr containing the
+ latches to the clustered index */
+ enum blob_op op) /*! in: operation code */
+ __attribute__((nonnull, warn_unused_result));
/*******************************************************************//**
Frees the space in an externally stored field to the file space
diff --git a/storage/innodb_plugin/include/btr0cur.ic b/storage/innodb_plugin/include/btr0cur.ic
index cd3a5d895bb..e31f77c77eb 100644
--- a/storage/innodb_plugin/include/btr0cur.ic
+++ b/storage/innodb_plugin/include/btr0cur.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
btr_cur_t* cursor, /*!< in: btr cursor */
mtr_t* mtr) /*!< in: mtr */
{
- page_t* page;
+ const page_t* page;
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
@@ -197,4 +197,25 @@ btr_cur_can_delete_without_compress(
return(TRUE);
}
+
+/*******************************************************************//**
+Determine if an operation on off-page columns is an update.
+@return TRUE if op != BTR_STORE_INSERT */
+UNIV_INLINE
+ibool
+btr_blob_op_is_update(
+/*==================*/
+ enum blob_op op) /*!< in: operation */
+{
+ switch (op) {
+ case BTR_STORE_INSERT:
+ return(FALSE);
+ case BTR_STORE_INSERT_UPDATE:
+ case BTR_STORE_UPDATE:
+ return(TRUE);
+ }
+
+ ut_ad(0);
+ return(FALSE);
+}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
index 489d1bec5b6..de009a4c670 100644
--- a/storage/innodb_plugin/include/buf0buf.h
+++ b/storage/innodb_plugin/include/buf0buf.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, 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
*****************************************************************************/
@@ -468,6 +468,31 @@ buf_block_get_modify_clock(
#else /* !UNIV_HOTBACKUP */
# define buf_block_modify_clock_inc(block) ((void) 0)
#endif /* !UNIV_HOTBACKUP */
+/*******************************************************************//**
+Increments the bufferfix count. */
+UNIV_INLINE
+void
+buf_block_buf_fix_inc_func(
+/*=======================*/
+#ifdef UNIV_SYNC_DEBUG
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line */
+#endif /* UNIV_SYNC_DEBUG */
+ buf_block_t* block) /*!< in/out: block to bufferfix */
+ __attribute__((nonnull));
+#ifdef UNIV_SYNC_DEBUG
+/** Increments the bufferfix count.
+@param b in/out: block to bufferfix
+@param f in: file name where requested
+@param l in: line number where requested */
+# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
+#else /* UNIV_SYNC_DEBUG */
+/** Increments the bufferfix count.
+@param b in/out: block to bufferfix
+@param f in: file name where requested
+@param l in: line number where requested */
+# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
+#endif /* UNIV_SYNC_DEBUG */
/********************************************************************//**
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value
diff --git a/storage/innodb_plugin/include/buf0buf.ic b/storage/innodb_plugin/include/buf0buf.ic
index 0fe1dbc2da5..e7308d77983 100644
--- a/storage/innodb_plugin/include/buf0buf.ic
+++ b/storage/innodb_plugin/include/buf0buf.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,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
*****************************************************************************/
@@ -916,19 +916,6 @@ buf_block_buf_fix_inc_func(
block->page.buf_fix_count++;
}
-#ifdef UNIV_SYNC_DEBUG
-/** Increments the bufferfix count.
-@param b in/out: block to bufferfix
-@param f in: file name where requested
-@param l in: line number where requested */
-# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
-#else /* UNIV_SYNC_DEBUG */
-/** Increments the bufferfix count.
-@param b in/out: block to bufferfix
-@param f in: file name where requested
-@param l in: line number where requested */
-# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
-#endif /* UNIV_SYNC_DEBUG */
/*******************************************************************//**
Decrements the bufferfix count. */
diff --git a/storage/innodb_plugin/include/fsp0fsp.h b/storage/innodb_plugin/include/fsp0fsp.h
index 403e1d404a8..8506748ae03 100644
--- a/storage/innodb_plugin/include/fsp0fsp.h
+++ b/storage/innodb_plugin/include/fsp0fsp.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, 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
*****************************************************************************/
@@ -176,30 +176,33 @@ fseg_n_reserved_pages(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize
file space fragmentation.
-@return the allocated page offset FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header, /*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction, /*!< in: if the new page is needed because
+@param[in/out] seg_header segment header
+@param[in] hint hint of which page would be desirable
+@param[in] direction if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in: mtr handle */
+ FSP_UP, FSP_NO_DIR
+@param[in/out] mtr mini-transaction
+@return X-latched block, or NULL if no page could be allocated */
+#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
+ fseg_alloc_free_page_general(seg_header, hint, direction, \
+ FALSE, mtr, mtr)
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
-ulint
+buf_block_t*
fseg_alloc_free_page_general(
/*=========================*/
fseg_header_t* seg_header,/*!< in/out: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
@@ -210,8 +213,12 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- __attribute__((warn_unused_result, nonnull(1,5)));
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
+ __attribute__((warn_unused_result, nonnull));
/**********************************************************************//**
Reserves free pages from a tablespace. All mini-transactions which may
use several pages from the tablespace should call this function beforehand
diff --git a/storage/innodb_plugin/include/log0log.h b/storage/innodb_plugin/include/log0log.h
index 8fce4ef96bc..8c61244a38d 100644
--- a/storage/innodb_plugin/include/log0log.h
+++ b/storage/innodb_plugin/include/log0log.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,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
*****************************************************************************/
diff --git a/storage/innodb_plugin/include/mem0mem.ic b/storage/innodb_plugin/include/mem0mem.ic
index cbce2edc661..bf7b1c20cb4 100644
--- a/storage/innodb_plugin/include/mem0mem.ic
+++ b/storage/innodb_plugin/include/mem0mem.ic
@@ -209,10 +209,6 @@ mem_heap_alloc(
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
#endif
-#ifdef UNIV_SET_MEM_TO_ZERO
- UNIV_MEM_ALLOC(buf, n);
- memset(buf, '\0', n);
-#endif
UNIV_MEM_ALLOC(buf, n);
return(buf);
}
diff --git a/storage/innodb_plugin/include/mtr0mtr.h b/storage/innodb_plugin/include/mtr0mtr.h
index 8a9ec8ea7f0..ecbfe750577 100644
--- a/storage/innodb_plugin/include/mtr0mtr.h
+++ b/storage/innodb_plugin/include/mtr0mtr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, 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
*****************************************************************************/
@@ -50,7 +50,9 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#define MTR_MEMO_PAGE_S_FIX RW_S_LATCH
#define MTR_MEMO_PAGE_X_FIX RW_X_LATCH
#define MTR_MEMO_BUF_FIX RW_NO_LATCH
-#define MTR_MEMO_MODIFY 54
+#ifdef UNIV_DEBUG
+# define MTR_MEMO_MODIFY 54
+#endif /* UNIV_DEBUG */
#define MTR_MEMO_S_LOCK 55
#define MTR_MEMO_X_LOCK 56
@@ -378,11 +380,14 @@ struct mtr_struct{
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
ibool modifications;
- /* TRUE if the mtr made modifications to
- buffer pool pages */
+ /*!< TRUE if the mini-transaction
+ modified buffer pool pages */
ulint n_log_recs;
/* count of how many page initial log records
have been written to the mtr log */
+ ulint n_freed_pages;
+ /* number of pages that have been freed in
+ this mini-transaction */
ulint log_mode; /* specifies which operations should be
logged; default value MTR_LOG_ALL */
ib_uint64_t start_lsn;/* start lsn of the possible log entry for
diff --git a/storage/innodb_plugin/include/mtr0mtr.ic b/storage/innodb_plugin/include/mtr0mtr.ic
index 9f92d2b06a1..4489e8e1c1e 100644
--- a/storage/innodb_plugin/include/mtr0mtr.ic
+++ b/storage/innodb_plugin/include/mtr0mtr.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, 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
*****************************************************************************/
@@ -45,6 +45,7 @@ mtr_start(
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
mtr->n_log_recs = 0;
+ mtr->n_freed_pages = 0;
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
diff --git a/storage/innodb_plugin/include/page0page.h b/storage/innodb_plugin/include/page0page.h
index ea9c212581c..e06276df2fd 100644
--- a/storage/innodb_plugin/include/page0page.h
+++ b/storage/innodb_plugin/include/page0page.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -281,16 +281,42 @@ page_get_supremum_offset(
const page_t* page); /*!< in: page which must have record(s) */
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
+
/************************************************************//**
-Returns the middle record of record list. If there are an even number
-of records in the list, returns the first record of upper half-list.
-@return middle record */
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
UNIV_INTERN
+const rec_t*
+page_rec_get_nth_const(
+/*===================*/
+ const page_t* page, /*!< in: page */
+ ulint nth) /*!< in: nth record */
+ __attribute__((nonnull, warn_unused_result));
+/************************************************************//**
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
+UNIV_INLINE
+rec_t*
+page_rec_get_nth(
+/*=============*/
+ page_t* page, /*< in: page */
+ ulint nth) /*!< in: nth record */
+ __attribute__((nonnull, warn_unused_result));
+
+#ifndef UNIV_HOTBACKUP
+/************************************************************//**
+Returns the middle record of the records on the page. If there is an
+even number of records in the list, returns the first record of the
+upper half-list.
+@return middle record */
+UNIV_INLINE
rec_t*
page_get_middle_rec(
/*================*/
- page_t* page); /*!< in: page */
-#ifndef UNIV_HOTBACKUP
+ page_t* page) /*!< in: page */
+ __attribute__((nonnull, warn_unused_result));
/*************************************************************//**
Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an
@@ -345,6 +371,7 @@ page_get_n_recs(
/***************************************************************//**
Returns the number of records before the given record in chain.
The number includes infimum and supremum records.
+This is the inverse function of page_rec_get_nth().
@return number of records */
UNIV_INTERN
ulint
diff --git a/storage/innodb_plugin/include/page0page.ic b/storage/innodb_plugin/include/page0page.ic
index b096a5ba321..7425d9d9cfe 100644
--- a/storage/innodb_plugin/include/page0page.ic
+++ b/storage/innodb_plugin/include/page0page.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -420,7 +420,37 @@ page_rec_is_infimum(
return(page_rec_is_infimum_low(page_offset(rec)));
}
+/************************************************************//**
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
+UNIV_INLINE
+rec_t*
+page_rec_get_nth(
+/*=============*/
+ page_t* page, /*!< in: page */
+ ulint nth) /*!< in: nth record */
+{
+ return((rec_t*) page_rec_get_nth_const(page, nth));
+}
+
#ifndef UNIV_HOTBACKUP
+/************************************************************//**
+Returns the middle record of the records on the page. If there is an
+even number of records in the list, returns the first record of the
+upper half-list.
+@return middle record */
+UNIV_INLINE
+rec_t*
+page_get_middle_rec(
+/*================*/
+ page_t* page) /*!< in: page */
+{
+ ulint middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
+
+ return(page_rec_get_nth(page, middle));
+}
+
/*************************************************************//**
Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an
diff --git a/storage/innodb_plugin/include/trx0rec.ic b/storage/innodb_plugin/include/trx0rec.ic
index e7e41d6d9f6..6c411047dc6 100644
--- a/storage/innodb_plugin/include/trx0rec.ic
+++ b/storage/innodb_plugin/include/trx0rec.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -107,6 +107,7 @@ trx_undo_rec_copy(
len = mach_read_from_2(undo_rec)
- ut_align_offset(undo_rec, UNIV_PAGE_SIZE);
+ ut_ad(len < UNIV_PAGE_SIZE);
return(mem_heap_dup(heap, undo_rec, len));
}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innodb_plugin/include/trx0rseg.ic b/storage/innodb_plugin/include/trx0rseg.ic
index daffa92fc7d..5e8d2b41120 100644
--- a/storage/innodb_plugin/include/trx0rseg.ic
+++ b/storage/innodb_plugin/include/trx0rseg.ic
@@ -25,6 +25,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "mtr0log.h"
+#include "trx0sys.h"
/******************************************************************//**
Gets a rollback segment header.
@@ -131,7 +132,13 @@ trx_rsegf_undo_find_free(
ulint i;
ulint page_no;
- for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
+ for (i = 0;
+#ifndef UNIV_DEBUG
+ i < TRX_RSEG_N_SLOTS;
+#else
+ i < (trx_rseg_n_slots_debug ? trx_rseg_n_slots_debug : TRX_RSEG_N_SLOTS);
+#endif
+ i++) {
page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr);
diff --git a/storage/innodb_plugin/include/trx0sys.h b/storage/innodb_plugin/include/trx0sys.h
index 78bb6fc349b..56fb801ee42 100644
--- a/storage/innodb_plugin/include/trx0sys.h
+++ b/storage/innodb_plugin/include/trx0sys.h
@@ -229,6 +229,12 @@ trx_id_t
trx_sys_get_new_trx_no(void);
/*========================*/
#endif /* !UNIV_HOTBACKUP */
+
+#ifdef UNIV_DEBUG
+/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
+extern uint trx_rseg_n_slots_debug;
+#endif
+
/*****************************************************************//**
Writes a trx id to an index page. In case that the id size changes in
some future version, this function should be used instead of
diff --git a/storage/innodb_plugin/include/trx0undo.h b/storage/innodb_plugin/include/trx0undo.h
index c95f99d6417..585b5f36696 100644
--- a/storage/innodb_plugin/include/trx0undo.h
+++ b/storage/innodb_plugin/include/trx0undo.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -194,16 +194,17 @@ trx_undo_get_first_rec(
mtr_t* mtr); /*!< in: mtr */
/********************************************************************//**
Tries to add a page to the undo log segment where the undo log is placed.
-@return page number if success, else FIL_NULL */
+@return X-latched block if success, else NULL */
UNIV_INTERN
-ulint
+buf_block_t*
trx_undo_add_page(
/*==============*/
trx_t* trx, /*!< in: transaction */
trx_undo_t* undo, /*!< in: undo log memory object */
- mtr_t* mtr); /*!< in: mtr which does not have a latch to any
+ mtr_t* mtr) /*!< in: mtr which does not have a latch to any
undo log page; the caller must have reserved
the rollback segment mutex */
+ __attribute__((nonnull, warn_unused_result));
/********************************************************************//**
Frees the last undo log page.
The caller must hold the rollback segment mutex. */
diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i
index 8a4d8a55370..4e9fbef4db3 100644
--- a/storage/innodb_plugin/include/univ.i
+++ b/storage/innodb_plugin/include/univ.i
@@ -146,14 +146,6 @@ Sun Studio */
/* DEBUG VERSION CONTROL
===================== */
-/* The following flag will make InnoDB to initialize
-all memory it allocates to zero. It hides Purify
-warnings about reading unallocated memory unless
-memory is read outside the allocated blocks. */
-/*
-#define UNIV_INIT_MEM_TO_ZERO
-*/
-
/* When this macro is defined then additional test functions will be
compiled. These functions live at the end of each relevant source file
and have "test_" prefix. These functions are not called from anywhere in
@@ -218,15 +210,6 @@ operations (very slow); also UNIV_DEBUG must be defined */
#define UNIV_BTR_DEBUG /* check B-tree links */
#define UNIV_LIGHT_MEM_DEBUG /* light memory debugging */
-#ifdef HAVE_purify
-/* The following sets all new allocated memory to zero before use:
-this can be used to eliminate unnecessary Purify warnings, but note that
-it also masks many bugs Purify could detect. For detailed Purify analysis it
-is best to remove the define below and look through the warnings one
-by one. */
-#define UNIV_SET_MEM_TO_ZERO
-#endif
-
/*
#define UNIV_SQL_DEBUG
#define UNIV_LOG_DEBUG
diff --git a/storage/innodb_plugin/include/ut0mem.h b/storage/innodb_plugin/include/ut0mem.h
index 9c6ee9049ec..5002c9e3801 100644
--- a/storage/innodb_plugin/include/ut0mem.h
+++ b/storage/innodb_plugin/include/ut0mem.h
@@ -78,40 +78,19 @@ ut_mem_init(void);
/*=============*/
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined and set_to_zero is TRUE.
+Allocates memory.
@return own: allocated memory */
UNIV_INTERN
void*
ut_malloc_low(
/*==========*/
ulint n, /*!< in: number of bytes to allocate */
- ibool set_to_zero, /*!< in: TRUE if allocated memory
- should be set to zero if
- UNIV_SET_MEM_TO_ZERO is defined */
- ibool assert_on_error); /*!< in: if TRUE, we crash mysqld if
+ ibool assert_on_error) /*!< in: if TRUE, we crash mysqld if
the memory cannot be allocated */
+ __attribute__((malloc));
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined.
-@return own: allocated memory */
-UNIV_INTERN
-void*
-ut_malloc(
-/*======*/
- ulint n); /*!< in: number of bytes to allocate */
-#ifndef UNIV_HOTBACKUP
-/**********************************************************************//**
-Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
-out. It cannot be used if we want to return an error message. Prints to
-stderr a message if fails.
-@return TRUE if succeeded */
-UNIV_INTERN
-ibool
-ut_test_malloc(
-/*===========*/
- ulint n); /*!< in: try to allocate this many bytes */
-#endif /* !UNIV_HOTBACKUP */
+Allocates memory. */
+#define ut_malloc(n) ut_malloc_low(n, TRUE)
/**********************************************************************//**
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
a nop. */
diff --git a/storage/innodb_plugin/include/ut0rnd.ic b/storage/innodb_plugin/include/ut0rnd.ic
index a33813037ea..3ae12f69186 100644
--- a/storage/innodb_plugin/include/ut0rnd.ic
+++ b/storage/innodb_plugin/include/ut0rnd.ic
@@ -114,7 +114,7 @@ ut_rnd_interval(
rnd = ut_rnd_gen_ulint();
- return(low + (rnd % (high - low + 1)));
+ return(low + (rnd % (high - low)));
}
/*********************************************************//**
diff --git a/storage/innodb_plugin/log/log0log.c b/storage/innodb_plugin/log/log0log.c
index 4bb9abdc1a4..28456e6b907 100644
--- a/storage/innodb_plugin/log/log0log.c
+++ b/storage/innodb_plugin/log/log0log.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,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
*****************************************************************************/
diff --git a/storage/innodb_plugin/mem/mem0pool.c b/storage/innodb_plugin/mem/mem0pool.c
index 3291453eeb5..8a01be66506 100644
--- a/storage/innodb_plugin/mem/mem0pool.c
+++ b/storage/innodb_plugin/mem/mem0pool.c
@@ -223,11 +223,7 @@ mem_pool_create(
pool = ut_malloc(sizeof(mem_pool_t));
- /* We do not set the memory to zero (FALSE) in the pool,
- but only when allocated at a higher level in mem0mem.c.
- This is to avoid masking useful Purify warnings. */
-
- pool->buf = ut_malloc_low(size, FALSE, TRUE);
+ pool->buf = ut_malloc_low(size, TRUE);
pool->size = size;
mutex_create(&pool->mutex, SYNC_MEM_POOL);
diff --git a/storage/innodb_plugin/mtr/mtr0mtr.c b/storage/innodb_plugin/mtr/mtr0mtr.c
index 5fad61b2922..1988bbabbf3 100644
--- a/storage/innodb_plugin/mtr/mtr0mtr.c
+++ b/storage/innodb_plugin/mtr/mtr0mtr.c
@@ -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
*****************************************************************************/
diff --git a/storage/innodb_plugin/os/os0proc.c b/storage/innodb_plugin/os/os0proc.c
index 48922886f23..a0679e31570 100644
--- a/storage/innodb_plugin/os/os0proc.c
+++ b/storage/innodb_plugin/os/os0proc.c
@@ -111,9 +111,6 @@ os_mem_alloc_large(
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size;
os_fast_mutex_unlock(&ut_list_mutex);
-# ifdef UNIV_SET_MEM_TO_ZERO
- memset(ptr, '\0', size);
-# endif
UNIV_MEM_ALLOC(ptr, size);
return(ptr);
}
diff --git a/storage/innodb_plugin/page/page0cur.c b/storage/innodb_plugin/page/page0cur.c
index ab5aa257338..88ee6bc09a9 100644
--- a/storage/innodb_plugin/page/page0cur.c
+++ b/storage/innodb_plugin/page/page0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -1180,14 +1180,15 @@ page_cur_insert_rec_zip_reorg(
/* Before trying to reorganize the page,
store the number of preceding records on the page. */
pos = page_rec_get_n_recs_before(rec);
+ ut_ad(pos > 0);
if (page_zip_reorganize(block, index, mtr)) {
/* The page was reorganized: Find rec by seeking to pos,
and update *current_rec. */
- rec = page + PAGE_NEW_INFIMUM;
-
- while (--pos) {
- rec = page + rec_get_next_offs(rec, TRUE);
+ if (pos > 1) {
+ rec = page_rec_get_nth(page, pos - 1);
+ } else {
+ rec = page + PAGE_NEW_INFIMUM;
}
*current_rec = rec;
@@ -1283,6 +1284,12 @@ page_cur_insert_rec_zip(
insert_rec = page_cur_insert_rec_zip_reorg(
current_rec, block, index, insert_rec,
page, page_zip, mtr);
+#ifdef UNIV_DEBUG
+ if (insert_rec) {
+ rec_offs_make_valid(
+ insert_rec, index, offsets);
+ }
+#endif /* UNIV_DEBUG */
}
return(insert_rec);
diff --git a/storage/innodb_plugin/page/page0page.c b/storage/innodb_plugin/page/page0page.c
index 52f6678be0a..7b72a22fd1c 100644
--- a/storage/innodb_plugin/page/page0page.c
+++ b/storage/innodb_plugin/page/page0page.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, 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
*****************************************************************************/
@@ -1475,55 +1475,54 @@ page_dir_balance_slot(
}
}
-#ifndef UNIV_HOTBACKUP
/************************************************************//**
-Returns the middle record of the record list. If there are an even number
-of records in the list, returns the first record of the upper half-list.
-@return middle record */
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
UNIV_INTERN
-rec_t*
-page_get_middle_rec(
-/*================*/
- page_t* page) /*!< in: page */
+const rec_t*
+page_rec_get_nth_const(
+/*===================*/
+ const page_t* page, /*!< in: page */
+ ulint nth) /*!< in: nth record */
{
- page_dir_slot_t* slot;
- ulint middle;
+ const page_dir_slot_t* slot;
ulint i;
ulint n_owned;
- ulint count;
- rec_t* rec;
+ const rec_t* rec;
- /* This many records we must leave behind */
- middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
-
- count = 0;
+ ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
for (i = 0;; i++) {
slot = page_dir_get_nth_slot(page, i);
n_owned = page_dir_slot_get_n_owned(slot);
- if (count + n_owned > middle) {
+ if (n_owned > nth) {
break;
} else {
- count += n_owned;
+ nth -= n_owned;
}
}
ut_ad(i > 0);
slot = page_dir_get_nth_slot(page, i - 1);
- rec = (rec_t*) page_dir_slot_get_rec(slot);
- rec = page_rec_get_next(rec);
-
- /* There are now count records behind rec */
+ rec = page_dir_slot_get_rec(slot);
- for (i = 0; i < middle - count; i++) {
- rec = page_rec_get_next(rec);
+ if (page_is_comp(page)) {
+ do {
+ rec = page_rec_get_next_low(rec, TRUE);
+ ut_ad(rec);
+ } while (nth--);
+ } else {
+ do {
+ rec = page_rec_get_next_low(rec, FALSE);
+ ut_ad(rec);
+ } while (nth--);
}
return(rec);
}
-#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
Returns the number of records before the given record in chain.
@@ -1585,6 +1584,7 @@ page_rec_get_n_recs_before(
n--;
ut_ad(n >= 0);
+ ut_ad(n < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
return((ulint) n);
}
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index 2cbe1e13edc..9a603d5690f 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -23,6 +23,15 @@ Insert into a table
Created 4/20/1996 Heikki Tuuri
*******************************************************/
+#ifdef __WIN__
+/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
+# define DEBUG_SYNC_C(dummy) ((void) 0)
+#else
+# include "my_global.h" /* HAVE_* */
+# include "m_string.h" /* for my_sys.h */
+# include "my_sys.h" /* DEBUG_SYNC_C */
+#endif
+
#include "row0ins.h"
#ifdef UNIV_NONINL
@@ -345,9 +354,9 @@ row_ins_clust_index_entry_by_modify(
return(DB_LOCK_TABLE_FULL);
}
- err = btr_cur_pessimistic_update(0, cursor,
- heap, big_rec, update,
- 0, thr, mtr);
+ err = btr_cur_pessimistic_update(
+ BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update,
+ 0, thr, mtr);
}
return(err);
@@ -1989,6 +1998,7 @@ row_ins_index_entry_low(
ulint modify = 0; /* remove warning */
rec_t* insert_rec;
rec_t* rec;
+ ulint* offsets;
ulint err;
ulint n_unique;
big_rec_t* big_rec = NULL;
@@ -2092,6 +2102,64 @@ row_ins_index_entry_low(
err = row_ins_clust_index_entry_by_modify(
mode, &cursor, &heap, &big_rec, entry,
thr, &mtr);
+
+ if (big_rec) {
+ ut_a(err == DB_SUCCESS);
+ /* Write out the externally stored
+ columns while still x-latching
+ index->lock and block->lock. Allocate
+ pages for big_rec in the mtr that
+ modified the B-tree, but be sure to skip
+ any pages that were freed in mtr. We will
+ write out the big_rec pages before
+ committing the B-tree mini-transaction. If
+ the system crashes so that crash recovery
+ will not replay the mtr_commit(&mtr), the
+ big_rec pages will be left orphaned until
+ the pages are allocated for something else.
+
+ TODO: If the allocation extends the
+ tablespace, it will not be redo
+ logged, in either mini-transaction.
+ Tablespace extension should be
+ redo-logged in the big_rec
+ mini-transaction, so that recovery
+ will not fail when the big_rec was
+ written to the extended portion of the
+ file, in case the file was somehow
+ truncated in the crash. */
+
+ rec = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(
+ rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+
+ DEBUG_SYNC_C("before_row_ins_upd_extern");
+ err = btr_store_big_rec_extern_fields(
+ index, btr_cur_get_block(&cursor),
+ rec, offsets, big_rec, &mtr,
+ BTR_STORE_INSERT_UPDATE);
+ DEBUG_SYNC_C("after_row_ins_upd_extern");
+ /* If writing big_rec fails (for
+ example, because of DB_OUT_OF_FILE_SPACE),
+ the record will be corrupted. Even if
+ we did not update any externally
+ stored columns, our update could cause
+ the record to grow so that a
+ non-updated column was selected for
+ external storage. This non-update
+ would not have been written to the
+ undo log, and thus the record cannot
+ be rolled back.
+
+ However, because we have not executed
+ mtr_commit(mtr) yet, the update will
+ not be replayed in crash recovery, and
+ the following assertion failure will
+ effectively "roll back" the operation. */
+ ut_a(err == DB_SUCCESS);
+ goto stored_big_rec;
+ }
} else {
ut_ad(!n_ext);
err = row_ins_sec_index_entry_by_modify(
@@ -2120,10 +2188,13 @@ function_exit:
mtr_commit(&mtr);
if (UNIV_LIKELY_NULL(big_rec)) {
- rec_t* rec;
- ulint* offsets;
+ DBUG_EXECUTE_IF(
+ "row_ins_extern_checkpoint",
+ log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE););
+
mtr_start(&mtr);
+ DEBUG_SYNC_C("before_row_ins_extern_latch");
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0,
__FILE__, __LINE__, &mtr);
@@ -2131,10 +2202,13 @@ function_exit:
offsets = rec_get_offsets(rec, index, NULL,
ULINT_UNDEFINED, &heap);
+ DEBUG_SYNC_C("before_row_ins_extern");
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, &mtr, FALSE, big_rec);
+ rec, offsets, big_rec, &mtr, BTR_STORE_INSERT);
+ DEBUG_SYNC_C("after_row_ins_extern");
+stored_big_rec:
if (modify) {
dtuple_big_rec_free(big_rec);
} else {
diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c
index 647d0031635..7f59d7cf9e9 100644
--- a/storage/innodb_plugin/row/row0merge.c
+++ b/storage/innodb_plugin/row/row0merge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2012, 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
@@ -576,7 +576,7 @@ row_merge_buf_write(
REC_STATUS_ORDINARY,
entry, n_fields,
&extra_size);
- ut_ad(size > extra_size);
+ ut_ad(size >= extra_size);
ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES);
extra_size -= REC_N_NEW_EXTRA_BYTES;
size -= REC_N_NEW_EXTRA_BYTES;
@@ -2012,7 +2012,7 @@ row_merge_drop_index(
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
- static const char str1[] =
+ static const char sql[] =
"PROCEDURE DROP_INDEX_PROC () IS\n"
"BEGIN\n"
/* Rename the index, so that it will be dropped by
@@ -2036,9 +2036,19 @@ row_merge_drop_index(
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
- err = que_eval_sql(info, str1, FALSE, trx);
+ err = que_eval_sql(info, sql, FALSE, trx);
- ut_a(err == DB_SUCCESS);
+
+ if (err != DB_SUCCESS) {
+ /* Even though we ensure that DDL transactions are WAIT
+ and DEADLOCK free, we could encounter other errors e.g.,
+ DB_TOO_MANY_TRANSACTIONS. */
+ trx->error_state = DB_SUCCESS;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error: row_merge_drop_index failed "
+ "with error code: %lu.\n", (ulint) err);
+ }
/* Replace this index with another equivalent index for all
foreign key constraints on this table where this index is used */
@@ -2290,7 +2300,7 @@ row_merge_rename_indexes(
/* We use the private SQL parser of Innobase to generate the
query graphs needed in renaming indexes. */
- static const char rename_indexes[] =
+ static const char sql[] =
"PROCEDURE RENAME_INDEXES_PROC () IS\n"
"BEGIN\n"
"UPDATE SYS_INDEXES SET NAME=SUBSTR(NAME,1,LENGTH(NAME)-1)\n"
@@ -2306,7 +2316,7 @@ row_merge_rename_indexes(
pars_info_add_dulint_literal(info, "tableid", table->id);
- err = que_eval_sql(info, rename_indexes, FALSE, trx);
+ err = que_eval_sql(info, sql, FALSE, trx);
if (err == DB_SUCCESS) {
dict_index_t* index = dict_table_get_first_index(table);
@@ -2316,6 +2326,15 @@ row_merge_rename_indexes(
}
index = dict_table_get_next_index(index);
} while (index);
+ } else {
+ /* Even though we ensure that DDL transactions are WAIT
+ and DEADLOCK free, we could encounter other errors e.g.,
+ DB_TOO_MANY_TRANSACTIONS. */
+ trx->error_state = DB_SUCCESS;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error: row_merge_rename_indexes "
+ "failed with error code: %lu.\n", (ulint) err);
}
trx->op_info = "";
@@ -2354,7 +2373,7 @@ row_merge_rename_tables(
memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
} else {
ut_print_timestamp(stderr);
- fprintf(stderr, "InnoDB: too long table name: '%s', "
+ fprintf(stderr, " InnoDB: too long table name: '%s', "
"max length is %d\n", old_table->name,
MAX_FULL_NAME_LEN);
ut_error;
diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
index 6f689f9909d..36aad4f8ca2 100644
--- a/storage/innodb_plugin/row/row0mysql.c
+++ b/storage/innodb_plugin/row/row0mysql.c
@@ -1900,6 +1900,20 @@ err_exit:
}
break;
+ case DB_TOO_MANY_CONCURRENT_TRXS:
+ /* We already have .ibd file here. it should be deleted. */
+
+ if (table->space && !fil_delete_tablespace(table->space)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: not able to"
+ " delete tablespace %lu of table ",
+ (ulong) table->space);
+ ut_print_name(stderr, trx, TRUE, table->name);
+ fputs("!\n", stderr);
+ }
+ /* fall through */
+
case DB_DUPLICATE_KEY:
default:
/* We may also get err == DB_ERROR if the .ibd file for the
diff --git a/storage/innodb_plugin/row/row0row.c b/storage/innodb_plugin/row/row0row.c
index 9cdbbe76e04..7ec05f01821 100644
--- a/storage/innodb_plugin/row/row0row.c
+++ b/storage/innodb_plugin/row/row0row.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -243,19 +243,20 @@ row_build(
}
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- /* This condition can occur during crash recovery before
- trx_rollback_active() has completed execution.
-
- This condition is possible if the server crashed
- during an insert or update before
- btr_store_big_rec_extern_fields() did mtr_commit() all
- BLOB pointers to the clustered index record.
-
- If the record contains a null BLOB pointer, look up the
- transaction that holds the implicit lock on this record, and
- assert that it was recovered (and will soon be rolled back). */
- ut_a(!rec_offs_any_null_extern(rec, offsets)
- || trx_assert_recovered(row_get_rec_trx_id(rec, index, offsets)));
+ if (rec_offs_any_null_extern(rec, offsets)) {
+ /* This condition can occur during crash recovery
+ before trx_rollback_active() has completed execution.
+
+ This condition is possible if the server crashed
+ during an insert or update-by-delete-and-insert before
+ btr_store_big_rec_extern_fields() did mtr_commit() all
+ BLOB pointers to the freshly inserted clustered index
+ record. */
+ ut_a(trx_assert_recovered(
+ row_get_rec_trx_id(rec, index, offsets)));
+ ut_a(trx_undo_roll_ptr_is_insert(
+ row_get_rec_roll_ptr(rec, index, offsets)));
+ }
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) {
diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
index 32f21dbe198..54172e71a47 100644
--- a/storage/innodb_plugin/row/row0sel.c
+++ b/storage/innodb_plugin/row/row0sel.c
@@ -4362,7 +4362,9 @@ no_gap_lock:
applicable to unique secondary indexes. Current behaviour is
to widen the scope of a lock on an already delete marked record
if the same record is deleted twice by the same transaction */
- if (index == clust_index && unique_search) {
+ if (index == clust_index && unique_search
+ && !prebuilt->used_in_HANDLER) {
+
err = DB_RECORD_NOT_FOUND;
goto normal_return;
diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c
index aec3dc19b86..5d2d114161c 100644
--- a/storage/innodb_plugin/row/row0upd.c
+++ b/storage/innodb_plugin/row/row0upd.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -23,6 +23,15 @@ Update of a row
Created 12/27/1996 Heikki Tuuri
*******************************************************/
+#ifdef __WIN__
+/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
+# define DEBUG_SYNC_C(dummy) ((void) 0)
+#else
+# include "my_global.h" /* HAVE_* */
+# include "m_string.h" /* for my_sys.h */
+# include "my_sys.h" /* DEBUG_SYNC_C */
+#endif
+
#include "row0upd.h"
#ifdef UNIV_NONINL
@@ -1969,28 +1978,62 @@ row_upd_clust_rec(
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(index->table)));
- err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
- &heap, &big_rec, node->update,
- node->cmpl_info, thr, mtr);
- mtr_commit(mtr);
-
- if (err == DB_SUCCESS && big_rec) {
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- rec_t* rec;
+ err = btr_cur_pessimistic_update(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
+ &heap, &big_rec, node->update, node->cmpl_info, thr, mtr);
+ if (big_rec) {
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_t* rec;
rec_offs_init(offsets_);
- mtr_start(mtr);
+ ut_a(err == DB_SUCCESS);
+ /* Write out the externally stored
+ columns while still x-latching
+ index->lock and block->lock. Allocate
+ pages for big_rec in the mtr that
+ modified the B-tree, but be sure to skip
+ any pages that were freed in mtr. We will
+ write out the big_rec pages before
+ committing the B-tree mini-transaction. If
+ the system crashes so that crash recovery
+ will not replay the mtr_commit(&mtr), the
+ big_rec pages will be left orphaned until
+ the pages are allocated for something else.
+
+ TODO: If the allocation extends the tablespace, it
+ will not be redo logged, in either mini-transaction.
+ Tablespace extension should be redo-logged in the
+ big_rec mini-transaction, so that recovery will not
+ fail when the big_rec was written to the extended
+ portion of the file, in case the file was somehow
+ truncated in the crash. */
- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
rec = btr_cur_get_rec(btr_cur);
+ DEBUG_SYNC_C("before_row_upd_extern");
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- mtr, TRUE, big_rec);
- mtr_commit(mtr);
+ big_rec, mtr, BTR_STORE_UPDATE);
+ DEBUG_SYNC_C("after_row_upd_extern");
+ /* If writing big_rec fails (for example, because of
+ DB_OUT_OF_FILE_SPACE), the record will be corrupted.
+ Even if we did not update any externally stored
+ columns, our update could cause the record to grow so
+ that a non-updated column was selected for external
+ storage. This non-update would not have been written
+ to the undo log, and thus the record cannot be rolled
+ back.
+
+ However, because we have not executed mtr_commit(mtr)
+ yet, the update will not be replayed in crash
+ recovery, and the following assertion failure will
+ effectively "roll back" the operation. */
+ ut_a(err == DB_SUCCESS);
}
+ mtr_commit(mtr);
+
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
diff --git a/storage/innodb_plugin/trx/trx0rec.c b/storage/innodb_plugin/trx/trx0rec.c
index 2db98e029df..dc55690c9c3 100644
--- a/storage/innodb_plugin/trx/trx0rec.c
+++ b/storage/innodb_plugin/trx/trx0rec.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -1176,6 +1176,7 @@ trx_undo_report_row_operation(
trx_t* trx;
trx_undo_t* undo;
ulint page_no;
+ buf_block_t* undo_block;
trx_rseg_t* rseg;
mtr_t mtr;
ulint err = DB_SUCCESS;
@@ -1218,10 +1219,13 @@ trx_undo_report_row_operation(
if (UNIV_UNLIKELY(!undo)) {
/* Did not succeed */
+ ut_ad(err != DB_SUCCESS);
mutex_exit(&(trx->undo_mutex));
return(err);
}
+
+ ut_ad(err == DB_SUCCESS);
} else {
ut_ad(op_type == TRX_UNDO_MODIFY_OP);
@@ -1235,30 +1239,30 @@ trx_undo_report_row_operation(
if (UNIV_UNLIKELY(!undo)) {
/* Did not succeed */
+ ut_ad(err != DB_SUCCESS);
mutex_exit(&(trx->undo_mutex));
return(err);
}
+ ut_ad(err == DB_SUCCESS);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
}
- page_no = undo->last_page_no;
-
mtr_start(&mtr);
+ page_no = undo->last_page_no;
+ undo_block = buf_page_get_gen(
+ undo->space, undo->zip_size, page_no, RW_X_LATCH,
+ undo->guess_block, BUF_GET, __FILE__, __LINE__, &mtr);
+ buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE);
+
do {
- buf_block_t* undo_block;
page_t* undo_page;
ulint offset;
- undo_block = buf_page_get_gen(undo->space, undo->zip_size,
- page_no, RW_X_LATCH,
- undo->guess_block, BUF_GET,
- __FILE__, __LINE__, &mtr);
- buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE);
-
undo_page = buf_block_get_frame(undo_block);
+ ut_ad(page_no == buf_block_get_page_no(undo_block));
if (op_type == TRX_UNDO_INSERT_OP) {
offset = trx_undo_page_report_insert(
@@ -1335,12 +1339,12 @@ trx_undo_report_row_operation(
a pessimistic insert in a B-tree, and we must reserve the
counterpart of the tree latch, which is the rseg mutex. */
- mutex_enter(&(rseg->mutex));
-
- page_no = trx_undo_add_page(trx, undo, &mtr);
+ mutex_enter(&rseg->mutex);
+ undo_block = trx_undo_add_page(trx, undo, &mtr);
+ mutex_exit(&rseg->mutex);
- mutex_exit(&(rseg->mutex));
- } while (UNIV_LIKELY(page_no != FIL_NULL));
+ page_no = undo->last_page_no;
+ } while (undo_block != NULL);
/* Did not succeed: out of space */
err = DB_OUT_OF_FILE_SPACE;
diff --git a/storage/innodb_plugin/trx/trx0sys.c b/storage/innodb_plugin/trx/trx0sys.c
index 352fa6af219..daa65bfcef0 100644
--- a/storage/innodb_plugin/trx/trx0sys.c
+++ b/storage/innodb_plugin/trx/trx0sys.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -127,6 +127,11 @@ static const char* file_format_name_map[] = {
static const ulint FILE_FORMAT_NAME_N
= sizeof(file_format_name_map) / sizeof(file_format_name_map[0]);
+#ifdef UNIV_DEBUG
+/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
+uint trx_rseg_n_slots_debug = 0;
+#endif
+
#ifndef UNIV_HOTBACKUP
/** This is used to track the maximum file format id known to InnoDB. It's
updated via SET GLOBAL innodb_file_format_check = 'x' or when we open
@@ -242,9 +247,7 @@ trx_sys_create_doublewrite_buf(void)
{
buf_block_t* block;
buf_block_t* block2;
-#ifdef UNIV_SYNC_DEBUG
buf_block_t* new_block;
-#endif /* UNIV_SYNC_DEBUG */
byte* doublewrite;
byte* fseg_header;
ulint page_no;
@@ -323,10 +326,9 @@ start_again:
for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
+ FSP_EXTENT_SIZE / 2; i++) {
- page_no = fseg_alloc_free_page(fseg_header,
- prev_page_no + 1,
- FSP_UP, &mtr);
- if (page_no == FIL_NULL) {
+ new_block = fseg_alloc_free_page(
+ fseg_header, prev_page_no + 1, FSP_UP, &mtr);
+ if (new_block == NULL) {
fprintf(stderr,
"InnoDB: Cannot create doublewrite"
" buffer: you must\n"
@@ -347,13 +349,8 @@ start_again:
the page position in the tablespace, then the page
has not been written to in doublewrite. */
-#ifdef UNIV_SYNC_DEBUG
- new_block =
-#endif /* UNIV_SYNC_DEBUG */
- buf_page_get(TRX_SYS_SPACE, 0, page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(new_block,
- SYNC_NO_ORDER_CHECK);
+ ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
+ page_no = buf_block_get_page_no(new_block);
if (i == FSP_EXTENT_SIZE / 2) {
ut_a(page_no == FSP_EXTENT_SIZE);
diff --git a/storage/innodb_plugin/trx/trx0trx.c b/storage/innodb_plugin/trx/trx0trx.c
index 7f3a3fcb4bf..80f079423fe 100644
--- a/storage/innodb_plugin/trx/trx0trx.c
+++ b/storage/innodb_plugin/trx/trx0trx.c
@@ -1008,6 +1008,8 @@ trx_commit_off_kernel(
ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
+
+ trx->error_state = DB_SUCCESS;
}
/****************************************************************//**
diff --git a/storage/innodb_plugin/trx/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c
index 746f0808643..6cc21d6d4c1 100644
--- a/storage/innodb_plugin/trx/trx0undo.c
+++ b/storage/innodb_plugin/trx/trx0undo.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, 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
*****************************************************************************/
@@ -870,9 +870,9 @@ trx_undo_discard_latest_update_undo(
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
Tries to add a page to the undo log segment where the undo log is placed.
-@return page number if success, else FIL_NULL */
+@return X-latched block if success, else NULL */
UNIV_INTERN
-ulint
+buf_block_t*
trx_undo_add_page(
/*==============*/
trx_t* trx, /*!< in: transaction */
@@ -882,11 +882,10 @@ trx_undo_add_page(
the rollback segment mutex */
{
page_t* header_page;
+ buf_block_t* new_block;
page_t* new_page;
trx_rseg_t* rseg;
- ulint page_no;
ulint n_reserved;
- ibool success;
ut_ad(mutex_own(&(trx->undo_mutex)));
ut_ad(!mutex_own(&kernel_mutex));
@@ -896,37 +895,37 @@ trx_undo_add_page(
if (rseg->curr_size == rseg->max_size) {
- return(FIL_NULL);
+ return(NULL);
}
header_page = trx_undo_page_get(undo->space, undo->zip_size,
undo->hdr_page_no, mtr);
- success = fsp_reserve_free_extents(&n_reserved, undo->space, 1,
- FSP_UNDO, mtr);
- if (!success) {
+ if (!fsp_reserve_free_extents(&n_reserved, undo->space, 1,
+ FSP_UNDO, mtr)) {
- return(FIL_NULL);
+ return(NULL);
}
- page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR
- + TRX_UNDO_FSEG_HEADER,
- undo->top_page_no + 1, FSP_UP,
- TRUE, mtr);
+ new_block = fseg_alloc_free_page_general(
+ TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
+ + header_page,
+ undo->top_page_no + 1, FSP_UP, TRUE, mtr, mtr);
fil_space_release_free_extents(undo->space, n_reserved);
- if (page_no == FIL_NULL) {
+ if (new_block == NULL) {
/* No space left */
- return(FIL_NULL);
+ return(NULL);
}
- undo->last_page_no = page_no;
+ ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
+ buf_block_dbg_add_level(new_block, SYNC_TRX_UNDO_PAGE);
+ undo->last_page_no = buf_block_get_page_no(new_block);
- new_page = trx_undo_page_get(undo->space, undo->zip_size,
- page_no, mtr);
+ new_page = buf_block_get_frame(new_block);
trx_undo_page_init(new_page, undo->type, mtr);
@@ -935,7 +934,7 @@ trx_undo_add_page(
undo->size++;
rseg->curr_size++;
- return(page_no);
+ return(new_block);
}
/********************************************************************//**
diff --git a/storage/innodb_plugin/ut/ut0mem.c b/storage/innodb_plugin/ut/ut0mem.c
index 95fb2187b79..9f9eb1c4d49 100644
--- a/storage/innodb_plugin/ut/ut0mem.c
+++ b/storage/innodb_plugin/ut/ut0mem.c
@@ -84,17 +84,13 @@ ut_mem_init(void)
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined and set_to_zero is TRUE.
+Allocates memory.
@return own: allocated memory */
UNIV_INTERN
void*
ut_malloc_low(
/*==========*/
ulint n, /*!< in: number of bytes to allocate */
- ibool set_to_zero, /*!< in: TRUE if allocated memory should be
- set to zero if UNIV_SET_MEM_TO_ZERO is
- defined */
ibool assert_on_error)/*!< in: if TRUE, we crash mysqld if the
memory cannot be allocated */
{
@@ -106,12 +102,6 @@ ut_malloc_low(
ret = malloc(n);
ut_a(ret || !assert_on_error);
-#ifdef UNIV_SET_MEM_TO_ZERO
- if (set_to_zero) {
- memset(ret, '\0', n);
- UNIV_MEM_ALLOC(ret, n);
- }
-#endif
return(ret);
}
@@ -199,12 +189,6 @@ retry:
#endif
}
- if (set_to_zero) {
-#ifdef UNIV_SET_MEM_TO_ZERO
- memset(ret, '\0', n + sizeof(ut_mem_block_t));
-#endif
- }
-
UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
@@ -221,75 +205,11 @@ retry:
void* ret = malloc(n);
ut_a(ret || !assert_on_error);
-# ifdef UNIV_SET_MEM_TO_ZERO
- if (set_to_zero) {
- memset(ret, '\0', n);
- }
-# endif
return(ret);
#endif /* !UNIV_HOTBACKUP */
}
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined.
-@return own: allocated memory */
-UNIV_INTERN
-void*
-ut_malloc(
-/*======*/
- ulint n) /*!< in: number of bytes to allocate */
-{
-#ifndef UNIV_HOTBACKUP
- return(ut_malloc_low(n, TRUE, TRUE));
-#else /* !UNIV_HOTBACKUP */
- return(malloc(n));
-#endif /* !UNIV_HOTBACKUP */
-}
-
-#ifndef UNIV_HOTBACKUP
-/**********************************************************************//**
-Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
-out. It cannot be used if we want to return an error message. Prints to
-stderr a message if fails.
-@return TRUE if succeeded */
-UNIV_INTERN
-ibool
-ut_test_malloc(
-/*===========*/
- ulint n) /*!< in: try to allocate this many bytes */
-{
- void* ret;
-
- ret = malloc(n);
-
- if (ret == NULL) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: cannot allocate"
- " %lu bytes of memory for\n"
- "InnoDB: a BLOB with malloc! Total allocated memory\n"
- "InnoDB: by InnoDB %lu bytes."
- " Operating system errno: %d\n"
- "InnoDB: Check if you should increase"
- " the swap file or\n"
- "InnoDB: ulimits of your operating system.\n"
- "InnoDB: On FreeBSD check you have"
- " compiled the OS with\n"
- "InnoDB: a big enough maximum process size.\n",
- (ulong) n,
- (ulong) ut_total_allocated_memory,
- (int) errno);
- return(FALSE);
- }
-
- free(ret);
-
- return(TRUE);
-}
-#endif /* !UNIV_HOTBACKUP */
-
-/**********************************************************************//**
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
a nop. */
UNIV_INTERN
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index e15cc35f0f8..01bff11fb3d 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -1,6 +1,5 @@
/*
- Copyright (c) 2001-2007 MySQL AB, 2008-2010 Sun Microsystems, Inc.
- Use is subject to license terms.
+ Copyright (c) 2001, 2011, 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
diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c
index 5f2334d20a1..85557b5e6c4 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2001, 2010, Oracle and/or its affiliates
+ Copyright (c) 2001, 2011, Oracle and/or its affiliates
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
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 35919a7bf36..e7b61256076 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates
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
@@ -4307,13 +4307,6 @@ int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename)
u_ptr->seg=keyseg;
keyseg+=u_ptr->keysegs+1;
}
- if (share.options & HA_OPTION_COMPRESS_RECORD)
- share.base.records=max_records=info.state->records;
- else if (share.base.min_pack_length)
- max_records=(ha_rows) (my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)) /
- (ulong) share.base.min_pack_length);
- else
- max_records=0;
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
(param->testflag & T_UNPACK);
share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
@@ -4323,10 +4316,17 @@ int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename)
set_if_bigger(file_length,param->max_data_file_length);
set_if_bigger(file_length,tmp_length);
set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
+
+ if (share.options & HA_OPTION_COMPRESS_RECORD)
+ share.base.records= max_records= info.state->records;
+ else if (!(share.options & HA_OPTION_PACK_RECORD))
+ max_records= (ha_rows) (file_length / share.base.pack_reclength);
+ else
+ max_records= 0;
VOID(mi_close(*org_info));
bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=max(max_records,share.base.records);
+ create_info.max_rows= max_records;
create_info.reloc_rows=share.base.reloc;
create_info.old_options=(share.options |
(unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c
index 56e66cccf7d..faa8196cb44 100644
--- a/storage/myisam/mi_close.c
+++ b/storage/myisam/mi_close.c
@@ -1,6 +1,5 @@
/*
- Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms.
+ Copyright (c) 2000, 2011, 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
diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c
index 47e5f3246da..cce87d73783 100644
--- a/storage/myisam/mi_delete_all.c
+++ b/storage/myisam/mi_delete_all.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2010, Oracle and/or its affiliates
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c
index dde3817c5e2..bd8f67afd44 100644
--- a/storage/myisam/mi_packrec.c
+++ b/storage/myisam/mi_packrec.c
@@ -1,6 +1,5 @@
/*
- Copyright (c) 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms.
+ Copyright (c) 2000, 2011, 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
diff --git a/storage/myisam/mi_preload.c b/storage/myisam/mi_preload.c
index b5594f63d47..87c3293bc84 100644
--- a/storage/myisam/mi_preload.c
+++ b/storage/myisam/mi_preload.c
@@ -1,6 +1,5 @@
/*
- Copyright (c) 2003, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms.
+ Copyright (c) 2003, 2011, 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
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c
index e8e9465d838..edfccfc495d 100644
--- a/storage/xtradb/row/row0sel.c
+++ b/storage/xtradb/row/row0sel.c
@@ -4384,7 +4384,9 @@ no_gap_lock:
applicable to unique secondary indexes. Current behaviour is
to widen the scope of a lock on an already delete marked record
if the same record is deleted twice by the same transaction */
- if (index == clust_index && unique_search) {
+ if (index == clust_index && unique_search
+ && !prebuilt->used_in_HANDLER) {
+
err = DB_RECORD_NOT_FOUND;
goto normal_return;