summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0pcur.c69
-rw-r--r--storage/innobase/dict/dict0dict.c4
-rw-r--r--storage/innobase/fsp/fsp0fsp.c32
-rw-r--r--storage/innobase/handler/ha_innodb.cc5
-rw-r--r--storage/innobase/include/db0err.h2
-rw-r--r--storage/innobase/include/trx0purge.h4
-rw-r--r--storage/innobase/row/row0ins.c3
-rw-r--r--storage/innobase/row/row0mysql.c24
-rw-r--r--storage/innobase/trx/trx0purge.c4
-rw-r--r--storage/innodb_plugin/ChangeLog32
-rw-r--r--storage/innodb_plugin/btr/btr0btr.c26
-rw-r--r--storage/innodb_plugin/btr/btr0pcur.c69
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c26
-rw-r--r--storage/innodb_plugin/fil/fil0fil.c59
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c37
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc6
-rw-r--r--storage/innodb_plugin/handler/handler0alter.cc12
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c6
-rw-r--r--storage/innodb_plugin/include/btr0btr.h7
-rw-r--r--storage/innodb_plugin/include/db0err.h2
-rw-r--r--storage/innodb_plugin/include/dict0dict.h14
-rw-r--r--storage/innodb_plugin/include/dict0dict.ic21
-rw-r--r--storage/innodb_plugin/include/dict0mem.h10
-rw-r--r--storage/innodb_plugin/include/fil0fil.h15
-rw-r--r--storage/innodb_plugin/include/sync0rw.ic4
-rw-r--r--storage/innodb_plugin/include/trx0purge.h4
-rw-r--r--storage/innodb_plugin/lock/lock0lock.c14
-rw-r--r--storage/innodb_plugin/row/row0ins.c3
-rw-r--r--storage/innodb_plugin/row/row0mysql.c60
-rw-r--r--storage/innodb_plugin/row/row0row.c14
-rw-r--r--storage/innodb_plugin/trx/trx0purge.c4
31 files changed, 376 insertions, 216 deletions
diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c
index 8d473794243..50aef035f2e 100644
--- a/storage/innobase/btr/btr0pcur.c
+++ b/storage/innobase/btr/btr0pcur.c
@@ -291,13 +291,19 @@ btr_pcur_restore_position(
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
- if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
mode = PAGE_CUR_LE;
- } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
+ break;
+ case BTR_PCUR_AFTER:
mode = PAGE_CUR_G;
- } else {
- ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
+ break;
+ case BTR_PCUR_BEFORE:
mode = PAGE_CUR_L;
+ break;
+ default:
+ ut_error;
+ mode = 0; /* silence a warning */
}
btr_pcur_open_with_no_init(index, tuple, mode, latch_mode,
@@ -306,26 +312,45 @@ btr_pcur_restore_position(
/* Restore the old search mode */
cursor->search_mode = old_mode;
- if (cursor->rel_pos == BTR_PCUR_ON
- && btr_pcur_is_on_user_rec(cursor, mtr)
- && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
- rec_get_offsets(
- btr_pcur_get_rec(cursor), index,
- NULL, ULINT_UNDEFINED, &heap))) {
-
- /* We have to store the NEW value for the modify clock, since
- the cursor can now be on a different page! But we can retain
- the value of old_rec */
-
- cursor->block_when_stored = buf_block_align(
- btr_pcur_get_page(cursor));
- cursor->modify_clock = buf_block_get_modify_clock(
- cursor->block_when_stored);
- cursor->old_stored = BTR_PCUR_OLD_STORED;
+ if (btr_pcur_is_on_user_rec(cursor, mtr)) {
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
+ if (!cmp_dtuple_rec(
+ tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ index, NULL,
+ ULINT_UNDEFINED, &heap))) {
+
+ /* We have to store the NEW value for
+ the modify clock, since the cursor can
+ now be on a different page! But we can
+ retain the value of old_rec */
+
+ cursor->block_when_stored =
+ buf_block_align(
+ btr_pcur_get_page(cursor));
+ cursor->modify_clock =
+ buf_block_get_modify_clock(
+ cursor->block_when_stored);
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
- mem_heap_free(heap);
+ mem_heap_free(heap);
- return(TRUE);
+ return(TRUE);
+ }
+
+ break;
+ case BTR_PCUR_BEFORE:
+ page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
+ break;
+ case BTR_PCUR_AFTER:
+ page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
+ break;
+#ifdef UNIV_DEBUG
+ default:
+ ut_error;
+#endif /* UNIV_DEBUG */
+ }
}
mem_heap_free(heap);
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index beea0a2f411..b2baa81b73f 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -26,6 +26,8 @@ Created 1/8/1996 Heikki Tuuri
#include "pars0sym.h"
#include "que0que.h"
#include "rem0cmp.h"
+#include "m_string.h"
+#include "my_sys.h"
#ifndef UNIV_HOTBACKUP
# include "m_ctype.h" /* my_isspace() */
#endif /* !UNIV_HOTBACKUP */
@@ -1889,6 +1891,8 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign) /* in, own: foreign key struct */
{
+ ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0);
+
mem_heap_free(foreign->heap);
}
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index 90e6ad34a9a..b095d0a0275 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -245,13 +245,13 @@ fseg_n_reserved_pages_low(
/************************************************************************
Marks a page used. The page must reside within the extents of the given
segment. */
-static
+static __attribute__((nonnull))
void
fseg_mark_page_used(
/*================*/
fseg_inode_t* seg_inode,/* in: segment inode */
- ulint space, /* in: space id */
ulint page, /* in: page offset */
+ xdes_t* descr, /* in: extent descriptor */
mtr_t* mtr); /* in: mtr */
/**************************************************************************
Returns the first extent descriptor for a segment. We think of the extent
@@ -635,10 +635,8 @@ xdes_calc_descriptor_index(
/************************************************************************
Gets pointer to a the extent descriptor of a page. The page where the extent
-descriptor resides is x-locked. If the page offset is equal to the free limit
-of the space, adds new extents from above the free limit to the space free
-list, if not free limit == space size. This adding is necessary to make the
-descriptor defined, as they are uninitialized above the free limit. */
+descriptor resides is x-locked. This function no longer extends the data
+file. */
UNIV_INLINE
xdes_t*
xdes_get_descriptor_with_space_hdr(
@@ -666,19 +664,10 @@ xdes_get_descriptor_with_space_hdr(
limit = mtr_read_ulint(sp_header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
size = mtr_read_ulint(sp_header + FSP_SIZE, MLOG_4BYTES, mtr);
- /* If offset is >= size or > limit, return NULL */
-
- if ((offset >= size) || (offset > limit)) {
-
+ if ((offset >= size) || (offset >= limit)) {
return(NULL);
}
- /* If offset is == limit, fill free list of the space. */
-
- if (offset == limit) {
- fsp_fill_free_list(FALSE, space, sp_header, mtr);
- }
-
descr_page_no = xdes_calc_descriptor_page(offset);
if (descr_page_no == 0) {
@@ -2552,7 +2541,7 @@ fseg_alloc_free_page_low(
ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
- fseg_mark_page_used(seg_inode, space, ret_page, mtr);
+ fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
}
return(ret_page);
@@ -2946,22 +2935,17 @@ fsp_get_available_space_in_free_extents(
/************************************************************************
Marks a page used. The page must reside within the extents of the given
segment. */
-static
+static __attribute__((nonnull))
void
fseg_mark_page_used(
/*================*/
fseg_inode_t* seg_inode,/* in: segment inode */
- ulint space, /* in: space id */
ulint page, /* in: page offset */
+ xdes_t* descr, /* in: extent descriptor */
mtr_t* mtr) /* in: mtr */
{
- xdes_t* descr;
ulint not_full_n_used;
- ut_ad(seg_inode && mtr);
-
- descr = xdes_get_descriptor(space, page, mtr);
-
ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr)
== mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 7a97c5bd6b9..6d8c0078a6c 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -746,6 +746,10 @@ convert_error_code_to_mysql(
return(HA_ERR_RECORD_FILE_FULL);
+ } else if (error == (int) DB_TABLE_IN_FK_CHECK) {
+
+ return(HA_ERR_TABLE_IN_FK_CHECK);
+
} else if (error == (int) DB_TABLE_IS_BEING_USED) {
return(HA_ERR_WRONG_COMMAND);
@@ -4863,6 +4867,7 @@ ha_innobase::index_read(
DBUG_ENTER("index_read");
ut_a(prebuilt->trx == thd_to_trx(user_thd));
+ ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
ha_statistic_increment(&SSV::ha_read_key_count);
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index bab6fa46370..1514b19639c 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -82,6 +82,8 @@ Created 5/24/1996 Heikki Tuuri
#define DB_REFERENCING_NO_INDEX 52 /* the parent (referencing) table does
not have an index that contains the
foreign keys as its prefix columns */
+#define DB_TABLE_IN_FK_CHECK 53 /* table is being used in foreign
+ key check */
/* The following are partial failure codes */
#define DB_FAIL 1000
diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
index c4aab91a93a..fbae7eb9a6d 100644
--- a/storage/innobase/include/trx0purge.h
+++ b/storage/innobase/include/trx0purge.h
@@ -120,9 +120,9 @@ struct trx_purge_struct{
read_view_t* view; /* The purge will not remove undo logs
which are >= this view (purge view) */
mutex_t mutex; /* Mutex protecting the fields below */
- ulint n_pages_handled;/* Approximate number of undo log
+ ulonglong n_pages_handled;/* Approximate number of undo log
pages processed in purge */
- ulint handle_limit; /* Target of how many pages to get
+ ulonglong handle_limit; /* Target of how many pages to get
processed in the current purge */
/*------------------------------*/
/* The following two fields form the 'purge pointer' which advances
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index bb5c95a572b..785a0426195 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -1074,6 +1074,9 @@ row_ins_foreign_check_on_constraint(
release the latch. */
row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
+
+ DEBUG_SYNC_C("innodb_dml_cascade_dict_unfreeze");
+
row_mysql_freeze_data_dictionary(thr_get_trx(thr));
mtr_start(mtr);
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 6148b01af9d..e8b3c485b0e 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -31,6 +31,8 @@ Created 9/17/2000 Heikki Tuuri
#include "btr0sea.h"
#include "fil0fil.h"
#include "ibuf0ibuf.h"
+#include "m_string.h"
+#include "my_sys.h"
/* A dummy variable used to fool the compiler */
ibool row_mysql_identically_false = FALSE;
@@ -1373,6 +1375,8 @@ row_update_for_mysql(
return(DB_ERROR);
}
+ DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
+
trx->op_info = "updating or deleting";
row_mysql_delay_if_needed();
@@ -3652,6 +3656,7 @@ row_rename_table_for_mysql(
ulint n_constraints_to_drop = 0;
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
+ ulint retry = 0;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
@@ -3750,6 +3755,25 @@ row_rename_table_for_mysql(
}
}
+ /* Is a foreign key check running on this table? */
+ for (retry = 0; retry < 100
+ && table->n_foreign_key_checks_running > 0; ++retry) {
+ row_mysql_unlock_data_dictionary(trx);
+ os_thread_yield();
+ row_mysql_lock_data_dictionary(trx);
+ }
+
+ if (table->n_foreign_key_checks_running > 0) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: in ALTER TABLE ", stderr);
+ ut_print_name(stderr, trx, TRUE, old_name);
+ fprintf(stderr, "\n"
+ "InnoDB: a FOREIGN KEY check is running.\n"
+ "InnoDB: Cannot rename table.\n");
+ err = DB_TABLE_IN_FK_CHECK;
+ goto funct_exit;
+ }
+
/* We use the private SQL parser of Innobase to generate the query
graphs needed in deleting the dictionary data from system tables in
Innobase. Deleting a row from SYS_INDEXES table also frees the file
diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c
index 9e09efc82b2..6fe5855ebfa 100644
--- a/storage/innobase/trx/trx0purge.c
+++ b/storage/innobase/trx/trx0purge.c
@@ -1022,7 +1022,7 @@ trx_purge(void)
{
que_thr_t* thr;
/* que_thr_t* thr2; */
- ulint old_pages_handled;
+ ulonglong old_pages_handled;
mutex_enter(&(purge_sys->mutex));
@@ -1116,7 +1116,7 @@ trx_purge(void)
(ulong) purge_sys->n_pages_handled);
}
- return(purge_sys->n_pages_handled - old_pages_handled);
+ return((ulint) (purge_sys->n_pages_handled - old_pages_handled));
}
/**********************************************************************
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index e1b241a5018..1588132fc8b 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,35 @@
+2012-03-15 The InnoDB Team
+
+ * fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/fil0fil.h,
+ lock/lock0lock.c:
+ Fix Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES
+ DIRECTLY FROM BUFFER POOL
+
+2012-03-15 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#13851171STRING OVERFLOW IN INNODB CODE FOUND BY STATIC
+ ANALYSIS
+
+2012-03-15 The InnoDB Team
+
+ * include/sync0rw.ic:
+ Fix Bug#13537504 VALGRIND: COND. JUMP/MOVE DEPENDS ON
+ UNINITIALISED VALUES IN OS_THREAD_EQ
+
+2012-03-08 The InnoDB Team
+
+ * btr/btr0pcur.c:
+ Fix Bug#13807811 BTR_PCUR_RESTORE_POSITION() CAN SKIP A RECORD
+
+2012-02-28 The InnoDB Team
+
+ * btr/btr0btr.c, dict/dict0dict.c, include/btr0btr.h,
+ include/dict0dict.h, include/dict0dict.ic, include/dict0mem.h,
+ handler/handler0alter.cc, row/row0mysql.c:
+ Fix Bug#12861864 RACE CONDITION IN BTR_GET_SIZE() AND
+ DROP INDEX/TABLE/DATABASE
+
2012-02-15 The InnoDB Team
* btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c, ibuf/ibuf0ibuf.c,
diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c
index 20eb30588fa..05723c26e2f 100644
--- a/storage/innodb_plugin/btr/btr0btr.c
+++ b/storage/innodb_plugin/btr/btr0btr.c
@@ -991,45 +991,49 @@ btr_page_alloc(
/**************************************************************//**
Gets the number of pages in a B-tree.
-@return number of pages */
+@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
UNIV_INTERN
ulint
btr_get_size(
/*=========*/
dict_index_t* index, /*!< in: index */
- ulint flag) /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ mtr_t* mtr) /*!< in/out: mini-transaction where index
+ is s-latched */
{
fseg_header_t* seg_header;
page_t* root;
ulint n;
ulint dummy;
- mtr_t mtr;
- mtr_start(&mtr);
+ ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
+ MTR_MEMO_S_LOCK));
- mtr_s_lock(dict_index_get_lock(index), &mtr);
+ if (index->page == FIL_NULL
+ || index->to_be_dropped
+ || *index->name == TEMP_INDEX_PREFIX) {
+ return(ULINT_UNDEFINED);
+ }
- root = btr_root_get(index, &mtr);
+ root = btr_root_get(index, mtr);
if (flag == BTR_N_LEAF_PAGES) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
- fseg_n_reserved_pages(seg_header, &n, &mtr);
+ fseg_n_reserved_pages(seg_header, &n, mtr);
} else if (flag == BTR_TOTAL_SIZE) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
- n = fseg_n_reserved_pages(seg_header, &dummy, &mtr);
+ n = fseg_n_reserved_pages(seg_header, &dummy, mtr);
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
- n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
+ n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
} else {
ut_error;
}
- mtr_commit(&mtr);
-
return(n);
}
diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c
index 57d9752649f..33700501bc5 100644
--- a/storage/innodb_plugin/btr/btr0pcur.c
+++ b/storage/innodb_plugin/btr/btr0pcur.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
@@ -121,6 +121,8 @@ btr_pcur_store_position(
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
+ ut_ad(page_is_leaf(page));
+ ut_ad(page_get_page_no(page) == index->page);
cursor->old_stored = BTR_PCUR_OLD_STORED;
@@ -313,13 +315,19 @@ btr_pcur_restore_position_func(
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
- if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
mode = PAGE_CUR_LE;
- } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
+ break;
+ case BTR_PCUR_AFTER:
mode = PAGE_CUR_G;
- } else {
- ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
+ break;
+ case BTR_PCUR_BEFORE:
mode = PAGE_CUR_L;
+ break;
+ default:
+ ut_error;
+ mode = 0;
}
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
@@ -328,25 +336,44 @@ btr_pcur_restore_position_func(
/* Restore the old search mode */
cursor->search_mode = old_mode;
- if (cursor->rel_pos == BTR_PCUR_ON
- && btr_pcur_is_on_user_rec(cursor)
- && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
- rec_get_offsets(
- btr_pcur_get_rec(cursor), index,
- NULL, ULINT_UNDEFINED, &heap))) {
-
- /* We have to store the NEW value for the modify clock, since
- the cursor can now be on a different page! But we can retain
- the value of old_rec */
+ if (btr_pcur_is_on_user_rec(cursor)) {
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
+ if (!cmp_dtuple_rec(
+ tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ index, NULL,
+ ULINT_UNDEFINED, &heap))) {
+
+ /* We have to store the NEW value for
+ the modify clock, since the cursor can
+ now be on a different page! But we can
+ retain the value of old_rec */
+
+ cursor->block_when_stored =
+ btr_pcur_get_block(cursor);
+ cursor->modify_clock =
+ buf_block_get_modify_clock(
+ cursor->block_when_stored);
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
- cursor->block_when_stored = btr_pcur_get_block(cursor);
- cursor->modify_clock = buf_block_get_modify_clock(
- cursor->block_when_stored);
- cursor->old_stored = BTR_PCUR_OLD_STORED;
+ mem_heap_free(heap);
- mem_heap_free(heap);
+ return(TRUE);
+ }
- return(TRUE);
+ break;
+ case BTR_PCUR_BEFORE:
+ page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
+ break;
+ case BTR_PCUR_AFTER:
+ page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
+ break;
+#ifdef UNIV_DEBUG
+ default:
+ ut_error;
+#endif /* UNIV_DEBUG */
+ }
}
mem_heap_free(heap);
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index 2d2262acf87..df7ac85681c 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -24,6 +24,8 @@ Created 1/8/1996 Heikki Tuuri
***********************************************************************/
#include "dict0dict.h"
+#include "m_string.h"
+#include "my_sys.h"
#ifdef UNIV_NONINL
#include "dict0dict.ic"
@@ -2272,6 +2274,8 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign) /*!< in, own: foreign key struct */
{
+ ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0);
+
mem_heap_free(foreign->heap);
}
@@ -4267,16 +4271,27 @@ dict_update_statistics(
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
&& dict_index_is_clust(index)))) {
+ mtr_t mtr;
ulint size;
- size = btr_get_size(index, BTR_TOTAL_SIZE);
- index->stat_index_size = size;
+ mtr_start(&mtr);
+ mtr_s_lock(dict_index_get_lock(index), &mtr);
+
+ size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
- sum_of_index_sizes += size;
+ if (size != ULINT_UNDEFINED) {
+ sum_of_index_sizes += size;
+ index->stat_index_size = size;
+ size = btr_get_size(
+ index, BTR_N_LEAF_PAGES, &mtr);
+ }
- size = btr_get_size(index, BTR_N_LEAF_PAGES);
+ mtr_commit(&mtr);
- if (size == 0) {
+ switch (size) {
+ case ULINT_UNDEFINED:
+ goto fake_statistics;
+ case 0:
/* The root node of the tree is a leaf */
size = 1;
}
@@ -4293,6 +4308,7 @@ dict_update_statistics(
various means, also via secondary indexes. */
ulint i;
+fake_statistics:
sum_of_index_sizes++;
index->stat_index_size = index->stat_n_leaf_pages = 1;
diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
index 01057c26d94..eebfbd9ccad 100644
--- a/storage/innodb_plugin/fil/fil0fil.c
+++ b/storage/innodb_plugin/fil/fil0fil.c
@@ -175,7 +175,7 @@ struct fil_space_struct {
.ibd file of tablespace and want to
stop temporarily posting of new i/o
requests on the file */
- ibool stop_ibuf_merges;
+ ibool stop_new_ops;
/*!< we set this TRUE when we start
deleting a single-table tablespace */
ibool is_being_deleted;
@@ -200,12 +200,13 @@ struct fil_space_struct {
ulint n_pending_flushes; /*!< this is positive when flushing
the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */
- ulint n_pending_ibuf_merges;/*!< this is positive
- when merging insert buffer entries to
- a page so that we may need to access
- the ibuf bitmap page in the
- tablespade: dropping of the tablespace
- is forbidden if this is positive */
+ ulint n_pending_ops;/*!< this is positive when we
+ have pending operations against this
+ tablespace. The pending operations can
+ be ibuf merges or lock validation code
+ trying to read a block.
+ Dropping of the tablespace is forbidden
+ if this is positive */
hash_node_t hash; /*!< hash chain node */
hash_node_t name_hash;/*!< hash chain the name_hash table */
#ifndef UNIV_HOTBACKUP
@@ -1236,7 +1237,7 @@ try_again:
}
space->stop_ios = FALSE;
- space->stop_ibuf_merges = FALSE;
+ space->stop_new_ops = FALSE;
space->is_being_deleted = FALSE;
space->purpose = purpose;
space->size = 0;
@@ -1245,7 +1246,7 @@ try_again:
space->n_reserved_extents = 0;
space->n_pending_flushes = 0;
- space->n_pending_ibuf_merges = 0;
+ space->n_pending_ops = 0;
UT_LIST_INIT(space->chain);
space->magic_n = FIL_SPACE_MAGIC_N;
@@ -1836,13 +1837,12 @@ fil_read_flushed_lsn_and_arch_log_no(
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
-Increments the count of pending insert buffer page merges, if space is not
-being deleted.
-@return TRUE if being deleted, and ibuf merges should be skipped */
+Increments the count of pending operation, if space is not being deleted.
+@return TRUE if being deleted, and operation should be skipped */
UNIV_INTERN
ibool
-fil_inc_pending_ibuf_merges(
-/*========================*/
+fil_inc_pending_ops(
+/*================*/
ulint id) /*!< in: space id */
{
fil_space_t* space;
@@ -1858,13 +1858,13 @@ fil_inc_pending_ibuf_merges(
(ulong) id);
}
- if (space == NULL || space->stop_ibuf_merges) {
+ if (space == NULL || space->stop_new_ops) {
mutex_exit(&fil_system->mutex);
return(TRUE);
}
- space->n_pending_ibuf_merges++;
+ space->n_pending_ops++;
mutex_exit(&fil_system->mutex);
@@ -1872,11 +1872,11 @@ fil_inc_pending_ibuf_merges(
}
/*******************************************************************//**
-Decrements the count of pending insert buffer page merges. */
+Decrements the count of pending operations. */
UNIV_INTERN
void
-fil_decr_pending_ibuf_merges(
-/*=========================*/
+fil_decr_pending_ops(
+/*=================*/
ulint id) /*!< in: space id */
{
fil_space_t* space;
@@ -1887,13 +1887,13 @@ fil_decr_pending_ibuf_merges(
if (space == NULL) {
fprintf(stderr,
- "InnoDB: Error: decrementing ibuf merge of a"
- " dropped tablespace %lu\n",
+ "InnoDB: Error: decrementing pending operation"
+ " of a dropped tablespace %lu\n",
(ulong) id);
}
if (space != NULL) {
- space->n_pending_ibuf_merges--;
+ space->n_pending_ops--;
}
mutex_exit(&fil_system->mutex);
@@ -2183,15 +2183,15 @@ fil_delete_tablespace(
char* path;
ut_a(id != 0);
-stop_ibuf_merges:
+stop_new_ops:
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(id);
if (space != NULL) {
- space->stop_ibuf_merges = TRUE;
+ space->stop_new_ops = TRUE;
- if (space->n_pending_ibuf_merges == 0) {
+ if (space->n_pending_ops == 0) {
mutex_exit(&fil_system->mutex);
count = 0;
@@ -2205,9 +2205,10 @@ stop_ibuf_merges:
ut_print_filename(stderr, space->name);
fprintf(stderr, ",\n"
"InnoDB: but there are %lu pending"
- " ibuf merges on it.\n"
+ " operations (most likely ibuf merges)"
+ " on it.\n"
"InnoDB: Loop %lu.\n",
- (ulong) space->n_pending_ibuf_merges,
+ (ulong) space->n_pending_ops,
(ulong) count);
}
@@ -2216,7 +2217,7 @@ stop_ibuf_merges:
os_thread_sleep(20000);
count++;
- goto stop_ibuf_merges;
+ goto stop_new_ops;
}
}
@@ -2242,7 +2243,7 @@ try_again:
}
ut_a(space);
- ut_a(space->n_pending_ibuf_merges == 0);
+ ut_a(space->n_pending_ops == 0);
space->is_being_deleted = TRUE;
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index c84cae302a6..e54629a7b67 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/fsp/fsp0fsp.c
@@ -273,15 +273,13 @@ fseg_n_reserved_pages_low(
/********************************************************************//**
Marks a page used. The page must reside within the extents of the given
segment. */
-static
+static __attribute__((nonnull))
void
fseg_mark_page_used(
/*================*/
fseg_inode_t* seg_inode,/*!< in: segment inode */
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
ulint page, /*!< in: page offset */
+ xdes_t* descr, /* extent descriptor */
mtr_t* mtr); /*!< in: mtr */
/**********************************************************************//**
Returns the first extent descriptor for a segment. We think of the extent
@@ -705,12 +703,10 @@ xdes_calc_descriptor_index(
/********************************************************************//**
Gets pointer to a the extent descriptor of a page. The page where the extent
-descriptor resides is x-locked. If the page offset is equal to the free limit
-of the space, adds new extents from above the free limit to the space free
-list, if not free limit == space size. This adding is necessary to make the
-descriptor defined, as they are uninitialized above the free limit.
+descriptor resides is x-locked. This function no longer extends the data
+file.
@return pointer to the extent descriptor, NULL if the page does not
-exist in the space or if the offset exceeds the free limit */
+exist in the space or if the offset is >= the free limit */
UNIV_INLINE __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor_with_space_hdr(
@@ -740,19 +736,10 @@ xdes_get_descriptor_with_space_hdr(
zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(sp_header + FSP_SPACE_FLAGS));
- /* If offset is >= size or > limit, return NULL */
-
- if ((offset >= size) || (offset > limit)) {
-
+ if ((offset >= size) || (offset >= limit)) {
return(NULL);
}
- /* If offset is == limit, fill free list of the space. */
-
- if (offset == limit) {
- fsp_fill_free_list(FALSE, space, sp_header, mtr);
- }
-
descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
if (descr_page_no == 0) {
@@ -2877,7 +2864,7 @@ got_hinted_page:
ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
- fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
+ fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
}
return(fsp_page_create(
@@ -3283,27 +3270,21 @@ fsp_get_available_space_in_free_extents(
/********************************************************************//**
Marks a page used. The page must reside within the extents of the given
segment. */
-static
+static __attribute__((nonnull))
void
fseg_mark_page_used(
/*================*/
fseg_inode_t* seg_inode,/*!< in: segment inode */
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
ulint page, /*!< in: page offset */
+ xdes_t* descr, /* extent descriptor */
mtr_t* mtr) /*!< in: mtr */
{
- xdes_t* descr;
ulint not_full_n_used;
- ut_ad(seg_inode && mtr);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
- descr = xdes_get_descriptor(space, zip_size, page, mtr);
-
ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr)
== mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index ccd4bc50941..5f22235091c 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -870,6 +870,9 @@ convert_error_code_to_mysql(
case DB_OUT_OF_FILE_SPACE:
return(HA_ERR_RECORD_FILE_FULL);
+ case DB_TABLE_IN_FK_CHECK:
+ return(HA_ERR_TABLE_IN_FK_CHECK);
+
case DB_TABLE_IS_BEING_USED:
return(HA_ERR_WRONG_COMMAND);
@@ -5591,6 +5594,7 @@ ha_innobase::index_read(
DBUG_ENTER("index_read");
ut_a(prebuilt->trx == thd_to_trx(user_thd));
+ ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
ha_statistic_increment(&SSV::ha_read_key_count);
@@ -6738,6 +6742,8 @@ ha_innobase::create(
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
}
+ ut_a(strlen(name) < sizeof(name2));
+
strcpy(name2, name);
normalize_table_name(norm_name, name2);
diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
index 485e03737e3..e2702b157af 100644
--- a/storage/innodb_plugin/handler/handler0alter.cc
+++ b/storage/innodb_plugin/handler/handler0alter.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 2005, 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
*****************************************************************************/
@@ -1010,7 +1010,9 @@ ha_innobase::prepare_drop_index(
goto func_exit;
}
+ rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = TRUE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
}
/* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
@@ -1129,7 +1131,9 @@ func_exit:
= dict_table_get_first_index(prebuilt->table);
do {
+ rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
index = dict_table_get_next_index(index);
} while (index);
}
@@ -1189,7 +1193,9 @@ ha_innobase::final_drop_index(
for (index = dict_table_get_first_index(prebuilt->table);
index; index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
}
goto func_exit;
diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
index f2b51c7ebed..f1da399167c 100644
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
@@ -3281,7 +3281,7 @@ ibuf_merge_or_delete_for_page(
function. When the counter is > 0, that prevents tablespace
from being dropped. */
- tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
+ tablespace_being_deleted = fil_inc_pending_ops(space);
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
/* Do not try to read the bitmap page from space;
@@ -3305,7 +3305,7 @@ ibuf_merge_or_delete_for_page(
mtr_commit(&mtr);
if (!tablespace_being_deleted) {
- fil_decr_pending_ibuf_merges(space);
+ fil_decr_pending_ops(space);
}
return;
@@ -3537,7 +3537,7 @@ reset_bit:
if (update_ibuf_bitmap && !tablespace_being_deleted) {
- fil_decr_pending_ibuf_merges(space);
+ fil_decr_pending_ops(space);
}
ibuf_exit();
diff --git a/storage/innodb_plugin/include/btr0btr.h b/storage/innodb_plugin/include/btr0btr.h
index 6e7bb8fc61e..793fbc76f3e 100644
--- a/storage/innodb_plugin/include/btr0btr.h
+++ b/storage/innodb_plugin/include/btr0btr.h
@@ -536,13 +536,16 @@ btr_parse_page_reorganize(
#ifndef UNIV_HOTBACKUP
/**************************************************************//**
Gets the number of pages in a B-tree.
-@return number of pages */
+@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
UNIV_INTERN
ulint
btr_get_size(
/*=========*/
dict_index_t* index, /*!< in: index */
- ulint flag); /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ mtr_t* mtr) /*!< in/out: mini-transaction where index
+ is s-latched */
+ __attribute__((nonnull, warn_unused_result));
/**************************************************************//**
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!
diff --git a/storage/innodb_plugin/include/db0err.h b/storage/innodb_plugin/include/db0err.h
index c7fa6d2a444..e4a3844cd22 100644
--- a/storage/innodb_plugin/include/db0err.h
+++ b/storage/innodb_plugin/include/db0err.h
@@ -97,6 +97,8 @@ enum db_err {
DB_FOREIGN_EXCEED_MAX_CASCADE, /* Foreign key constraint related
cascading delete/update exceeds
maximum allowed depth */
+ DB_TABLE_IN_FK_CHECK, /* table is being used in foreign
+ key check */
/* The following are partial failure codes */
DB_FAIL = 1000,
diff --git a/storage/innodb_plugin/include/dict0dict.h b/storage/innodb_plugin/include/dict0dict.h
index fdb3bd5d50c..e728c78b9c0 100644
--- a/storage/innodb_plugin/include/dict0dict.h
+++ b/storage/innodb_plugin/include/dict0dict.h
@@ -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
*****************************************************************************/
@@ -1018,14 +1018,6 @@ dict_index_get_page(
/*================*/
const dict_index_t* tree); /*!< in: index */
/*********************************************************************//**
-Sets the page number of the root of index tree. */
-UNIV_INLINE
-void
-dict_index_set_page(
-/*================*/
- dict_index_t* index, /*!< in/out: index */
- ulint page); /*!< in: page number */
-/*********************************************************************//**
Gets the read-write lock of the index tree.
@return read-write lock */
UNIV_INLINE
diff --git a/storage/innodb_plugin/include/dict0dict.ic b/storage/innodb_plugin/include/dict0dict.ic
index 1704e9c2d71..f3d73b09bdb 100644
--- a/storage/innodb_plugin/include/dict0dict.ic
+++ b/storage/innodb_plugin/include/dict0dict.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
*****************************************************************************/
@@ -723,21 +723,6 @@ dict_index_get_page(
}
/*********************************************************************//**
-Sets the page number of the root of index tree. */
-UNIV_INLINE
-void
-dict_index_set_page(
-/*================*/
- dict_index_t* index, /*!< in/out: index */
- ulint page) /*!< in: page number */
-{
- ut_ad(index);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- index->page = page;
-}
-
-/*********************************************************************//**
Gets the read-write lock of the index tree.
@return read-write lock */
UNIV_INLINE
diff --git a/storage/innodb_plugin/include/dict0mem.h b/storage/innodb_plugin/include/dict0mem.h
index bd32a239cfd..1b26aea38c9 100644
--- a/storage/innodb_plugin/include/dict0mem.h
+++ b/storage/innodb_plugin/include/dict0mem.h
@@ -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
*****************************************************************************/
@@ -305,7 +305,9 @@ struct dict_index_struct{
unsigned to_be_dropped:1;
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
- otherwise FALSE */
+ otherwise FALSE. Protected by
+ dict_sys->mutex, dict_operation_lock and
+ index->lock.*/
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)
diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h
index f6a19646292..c95038b9231 100644
--- a/storage/innodb_plugin/include/fil0fil.h
+++ b/storage/innodb_plugin/include/fil0fil.h
@@ -340,20 +340,19 @@ fil_read_flushed_lsn_and_arch_log_no(
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
/*******************************************************************//**
-Increments the count of pending insert buffer page merges, if space is not
-being deleted.
-@return TRUE if being deleted, and ibuf merges should be skipped */
+Increments the count of pending operation, if space is not being deleted.
+@return TRUE if being deleted, and operation should be skipped */
UNIV_INTERN
ibool
-fil_inc_pending_ibuf_merges(
-/*========================*/
+fil_inc_pending_ops(
+/*================*/
ulint id); /*!< in: space id */
/*******************************************************************//**
-Decrements the count of pending insert buffer page merges. */
+Decrements the count of pending operations. */
UNIV_INTERN
void
-fil_decr_pending_ibuf_merges(
-/*=========================*/
+fil_decr_pending_ops(
+/*=================*/
ulint id); /*!< in: space id */
#endif /* !UNIV_HOTBACKUP */
/*******************************************************************//**
diff --git a/storage/innodb_plugin/include/sync0rw.ic b/storage/innodb_plugin/include/sync0rw.ic
index 5eb3d017eca..cd997febc30 100644
--- a/storage/innodb_plugin/include/sync0rw.ic
+++ b/storage/innodb_plugin/include/sync0rw.ic
@@ -564,8 +564,6 @@ rw_lock_x_unlock_func(
if (lock->lock_word == 0) {
/* Last caller in a possible recursive chain. */
lock->recursive = FALSE;
- UNIV_MEM_INVALID(&lock->writer_thread,
- sizeof lock->writer_thread);
}
#ifdef UNIV_SYNC_DEBUG
@@ -606,8 +604,6 @@ rw_lock_x_unlock_direct(
if (lock->lock_word == 0) {
lock->recursive = FALSE;
- UNIV_MEM_INVALID(&lock->writer_thread,
- sizeof lock->writer_thread);
}
#ifdef UNIV_SYNC_DEBUG
diff --git a/storage/innodb_plugin/include/trx0purge.h b/storage/innodb_plugin/include/trx0purge.h
index 908760580f6..37d3795efb0 100644
--- a/storage/innodb_plugin/include/trx0purge.h
+++ b/storage/innodb_plugin/include/trx0purge.h
@@ -140,9 +140,9 @@ struct trx_purge_struct{
read_view_t* view; /*!< The purge will not remove undo logs
which are >= this view (purge view) */
mutex_t mutex; /*!< Mutex protecting the fields below */
- ulint n_pages_handled;/*!< Approximate number of undo log
+ ulonglong n_pages_handled;/*!< Approximate number of undo log
pages processed in purge */
- ulint handle_limit; /*!< Target of how many pages to get
+ ulonglong handle_limit; /*!< Target of how many pages to get
processed in the current purge */
/*------------------------------*/
/* The following two fields form the 'purge pointer' which advances
diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c
index c8bbc5c02bd..49f732da175 100644
--- a/storage/innodb_plugin/lock/lock0lock.c
+++ b/storage/innodb_plugin/lock/lock0lock.c
@@ -5040,9 +5040,17 @@ lock_validate(void)
lock_mutex_exit_kernel();
- lock_rec_validate_page(space,
- fil_space_get_zip_size(space),
- page_no);
+ /* Make sure that the tablespace is not
+ deleted while we are trying to access
+ the page. */
+ if (!fil_inc_pending_ops(space)) {
+ lock_rec_validate_page(
+ space,
+ fil_space_get_zip_size(space),
+ page_no);
+
+ fil_decr_pending_ops(space);
+ }
lock_mutex_enter_kernel();
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index 9a603d5690f..2d4afa6c5ed 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -1102,6 +1102,9 @@ row_ins_foreign_check_on_constraint(
release the latch. */
row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
+
+ DEBUG_SYNC_C("innodb_dml_cascade_dict_unfreeze");
+
row_mysql_freeze_data_dictionary(thr_get_trx(thr));
mtr_start(mtr);
diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
index 36aad4f8ca2..974d67893a3 100644
--- a/storage/innodb_plugin/row/row0mysql.c
+++ b/storage/innodb_plugin/row/row0mysql.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 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
*****************************************************************************/
@@ -52,6 +52,14 @@ Created 9/17/2000 Heikki Tuuri
#include "fil0fil.h"
#include "ibuf0ibuf.h"
+#ifdef __WIN__
+/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
+# define DEBUG_SYNC_C(dummy) ((void) 0)
+#else
+# include "m_string.h" /* for my_sys.h */
+# include "my_sys.h" /* DEBUG_SYNC_C */
+#endif
+
/** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
@@ -1350,6 +1358,8 @@ row_update_for_mysql(
return(DB_ERROR);
}
+ DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
+
trx->op_info = "updating or deleting";
row_mysql_delay_if_needed();
@@ -3013,6 +3023,7 @@ row_drop_table_for_mysql(
{
dict_foreign_t* foreign;
dict_table_t* table;
+ dict_index_t* index;
ulint space_id;
ulint err;
const char* table_name;
@@ -3219,6 +3230,18 @@ check_next_foreign:
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
trx->table_id = table->id;
+ /* Mark all indexes unavailable in the data dictionary cache
+ before starting to drop the table. */
+
+ for (index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(dict_index_get_lock(index));
+ ut_ad(!index->to_be_dropped);
+ index->to_be_dropped = TRUE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
+ }
+
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
@@ -3384,6 +3407,17 @@ check_next_foreign:
the undo log. We can directly exit here
and return the DB_TOO_MANY_CONCURRENT_TRXS
error. */
+
+ /* Mark all indexes available in the data dictionary
+ cache again. */
+
+ for (index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(dict_index_get_lock(index));
+ index->to_be_dropped = FALSE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
+ }
break;
case DB_OUT_OF_FILE_SPACE:
@@ -3741,6 +3775,7 @@ row_rename_table_for_mysql(
ulint n_constraints_to_drop = 0;
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
+ ulint retry = 0;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
@@ -3824,6 +3859,25 @@ row_rename_table_for_mysql(
}
}
+ /* Is a foreign key check running on this table? */
+ for (retry = 0; retry < 100
+ && table->n_foreign_key_checks_running > 0; ++retry) {
+ row_mysql_unlock_data_dictionary(trx);
+ os_thread_yield();
+ row_mysql_lock_data_dictionary(trx);
+ }
+
+ if (table->n_foreign_key_checks_running > 0) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: in ALTER TABLE ", stderr);
+ ut_print_name(stderr, trx, TRUE, old_name);
+ fprintf(stderr, "\n"
+ "InnoDB: a FOREIGN KEY check is running.\n"
+ "InnoDB: Cannot rename table.\n");
+ err = DB_TABLE_IN_FK_CHECK;
+ goto funct_exit;
+ }
+
/* We use the private SQL parser of Innobase to generate the query
graphs needed in updating the dictionary data from system tables. */
diff --git a/storage/innodb_plugin/row/row0row.c b/storage/innodb_plugin/row/row0row.c
index 7ec05f01821..c1f39fb68cb 100644
--- a/storage/innodb_plugin/row/row0row.c
+++ b/storage/innodb_plugin/row/row0row.c
@@ -245,15 +245,11 @@ row_build(
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
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)));
+ before trx_rollback_active() has completed execution,
+ or when a concurrently executing
+ row_ins_index_entry_low() has committed the B-tree
+ mini-transaction but has not yet managed to restore
+ the cursor position for writing the big_rec. */
ut_a(trx_undo_roll_ptr_is_insert(
row_get_rec_roll_ptr(rec, index, offsets)));
}
diff --git a/storage/innodb_plugin/trx/trx0purge.c b/storage/innodb_plugin/trx/trx0purge.c
index 1a70750083a..56607c9ff93 100644
--- a/storage/innodb_plugin/trx/trx0purge.c
+++ b/storage/innodb_plugin/trx/trx0purge.c
@@ -1085,7 +1085,7 @@ trx_purge(void)
{
que_thr_t* thr;
/* que_thr_t* thr2; */
- ulint old_pages_handled;
+ ulonglong old_pages_handled;
mutex_enter(&(purge_sys->mutex));
@@ -1179,7 +1179,7 @@ trx_purge(void)
(ulong) purge_sys->n_pages_handled);
}
- return(purge_sys->n_pages_handled - old_pages_handled);
+ return((ulint) (purge_sys->n_pages_handled - old_pages_handled));
}
/******************************************************************//**