From 685725eb006f51cedd93cc56b9ade8aa6d00c843 Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 30 Nov 2009 19:12:26 +0530 Subject: [PATCH] Applying InnoDB Plugin 1.0.6 snapshot, Fixes BUG#48469 applied revisions: r6201, r6202, r6207, r6208, r6210 r6202 - port fix for BUG#48469 to plugin Detailed revision comments: r6201 | marko | 2009-11-19 14:09:11 +0200 (Thu, 19 Nov 2009) | 2 lines branches/zip: ha_innobase::add_index(): Clarify the comment on orphaned tables when creating a primary key. r6202 | jyang | 2009-11-19 15:01:00 +0200 (Thu, 19 Nov 2009) | 8 lines branches/zip: Function fseg_free() is no longer defined in branches/zip. To port fix for bug #48469 to zip, we can use btr_free_root() which frees the page, and also does not require mini-transaction. Approved by Marko. r6207 | vasil | 2009-11-20 10:19:14 +0200 (Fri, 20 Nov 2009) | 54 lines branches/zip: Merge r6198:6206 from branches/5.1: (r6203 was skipped as it is already in branches/zip) ------------------------------------------------------------------------ r6200 | vasil | 2009-11-19 12:14:23 +0200 (Thu, 19 Nov 2009) | 4 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: White space fixup - indent under the opening ( ------------------------------------------------------------------------ r6203 | jyang | 2009-11-19 15:12:22 +0200 (Thu, 19 Nov 2009) | 8 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: Use btr_free_root() instead of fseg_free() for the fix of bug #48469, because fseg_free() is not defined in the zip branch. And we could save one mini-trasaction started by fseg_free(). Approved by Marko. ------------------------------------------------------------------------ r6205 | jyang | 2009-11-20 07:55:48 +0200 (Fri, 20 Nov 2009) | 11 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Add a special case to handle the Duplicated Key error and return DB_ERROR instead. This is to avoid a possible SIGSEGV by mysql error handling re-entering the storage layer for dup key info without proper table handle. This is to prevent a server crash when error situation in bug #45961 "DDL on partitioned innodb tables leaves data dictionary in an inconsistent state" happens. rb://157 approved by Sunny Bains. ------------------------------------------------------------------------ r6206 | jyang | 2009-11-20 09:38:43 +0200 (Fri, 20 Nov 2009) | 5 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Fix a minor code formating issue for the parenthesis iplacement of the if condition in rename_table(). ------------------------------------------------------------------------ r6208 | vasil | 2009-11-20 10:49:24 +0200 (Fri, 20 Nov 2009) | 4 lines branches/zip: Add ChangeLog entry for c6207. r6210 | vasil | 2009-11-20 23:39:48 +0200 (Fri, 20 Nov 2009) | 3 lines branches/zip: Whitespace fixup. --- storage/innodb_plugin/ChangeLog | 7 ++++++ storage/innodb_plugin/btr/btr0btr.c | 3 +-- storage/innodb_plugin/handler/ha_innodb.cc | 24 +++++++++++++++++++ .../innodb_plugin/handler/handler0alter.cc | 9 +++---- storage/innodb_plugin/trx/trx0i_s.c | 2 +- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index b801a3c23b2..1a6e07fd147 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2009-11-20 The InnoDB Team + + * handler/ha_innodb.cc: + Add a workaround to prevent a crash due to Bug#45961 DDL on + partitioned innodb tables leaves data dictionary in an inconsistent + state + 2009-11-19 The InnoDB Team * btr/btr0btr.c: diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 9f06a41aa1e..086b3a0a599 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -794,8 +794,7 @@ btr_create( PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { /* Not enough space for new segment, free root segment before return. */ - fseg_free(space, page_no, - PAGE_HEADER + PAGE_BTR_SEG_TOP); + btr_free_root(space, zip_size, page_no, mtr); return(FIL_NULL); } diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index cc84bbf209d..0dc845f83e0 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -793,6 +793,12 @@ convert_error_code_to_mysql( return(-1); /* unspecified error */ case DB_DUPLICATE_KEY: + /* Be cautious with returning this error, since + mysql could re-enter the storage layer to get + duplicated key info, the operation requires a + valid table handle and/or transaction information, + which might not always be available in the error + handling stage. */ return(HA_ERR_FOUND_DUPP_KEY); case DB_FOREIGN_DUPLICATE_KEY: @@ -6815,6 +6821,24 @@ ha_innobase::rename_table( innobase_commit_low(trx); trx_free_for_mysql(trx); + /* Add a special case to handle the Duplicated Key error + and return DB_ERROR instead. + This is to avoid a possible SIGSEGV error from mysql error + handling code. Currently, mysql handles the Duplicated Key + error by re-entering the storage layer and getting dup key + info by calling get_dup_key(). This operation requires a valid + table handle ('row_prebuilt_t' structure) which could no + longer be available in the error handling stage. The suggested + solution is to report a 'table exists' error message (since + the dup key error here is due to an existing table whose name + is the one we are trying to rename to) and return the generic + error code. */ + if (error == (int) DB_DUPLICATE_KEY) { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to); + + error = DB_ERROR; + } + error = convert_error_code_to_mysql(error, 0, NULL); DBUG_RETURN(error); diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc index f32cb1d4093..a5008991400 100644 --- a/storage/innodb_plugin/handler/handler0alter.cc +++ b/storage/innodb_plugin/handler/handler0alter.cc @@ -765,10 +765,11 @@ err_exit: ut_ad(error == DB_SUCCESS); /* Commit the data dictionary transaction in order to release - the table locks on the system tables. Unfortunately, this - means that if MySQL crashes while creating a new primary key - inside row_merge_build_indexes(), indexed_table will not be - dropped on crash recovery. Thus, it will become orphaned. */ + the table locks on the system tables. This means that if + MySQL crashes while creating a new primary key inside + row_merge_build_indexes(), indexed_table will not be dropped + by trx_rollback_active(). It will have to be recovered or + dropped by the database administrator. */ trx_commit_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); diff --git a/storage/innodb_plugin/trx/trx0i_s.c b/storage/innodb_plugin/trx/trx0i_s.c index 12562b40726..ef2e6850d6c 100644 --- a/storage/innodb_plugin/trx/trx0i_s.c +++ b/storage/innodb_plugin/trx/trx0i_s.c @@ -60,7 +60,7 @@ Created July 17, 2007 Vasil Dimov /** @brief The maximum number of chunks to allocate for a table cache. The rows of a table cache are stored in a set of chunks. When a new -row is added a new chunk is allocated if necessary. Assuming that the +row is added a new chunk is allocated if necessary. Assuming that the first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each subsequent is N/2 where N is the number of rows we have allocated till now, then 39th chunk would accommodate 1677416425 rows and all chunks