diff --git a/ChangeLog b/ChangeLog index 45f99504b677a189a47f41b409e0d2ffd4471d75..d727501ea9a504919d17732334429a52eb4db5e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2010-02-04 The InnoDB Team + + * btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, buf/buf0buf.c, + include/btr0btr.h, include/btr0cur.h, include/btr0pcur.h, + include/btr0pcur.ic, include/buf0buf.h, row/row0ins.c, row/row0sel.c: + Pass the file name and line number of the caller of the + b-tree cursor functions to the buffer pool requests, in order + to make the latch diagnostics more accurate. + +2010-02-03 The InnoDB Team + + * buf/buf0lru.c: + Fix Bug#35077 Very slow DROP TABLE (ALTER TABLE, OPTIMIZE TABLE) + on compressed tables + +2010-02-03 The InnoDB Team + + * handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c: + Clean up CHECK TABLE error handling. + +2010-02-01 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb-autoinc.test, + mysql-test/innodb-autoinc.result, + mysql-test/innodb-autoinc-44030.test, + mysql-test/innodb-autoinc-44030.result: + Fix Bug#49497 Error 1467 (ER_AUTOINC_READ_FAILED) on inserting + a negative value + +2010-01-27 The InnoDB Team + + * include/row0mysql.h, log/log0recv.c, row/row0mysql.c: + Drop temporary tables at startup. + This addresses the third aspect of + Bug#41609 Crash recovery does not work for InnoDB temporary tables. + 2010-01-21 The InnoDB Team * buf/buf0buf.c: diff --git a/btr/btr0btr.c b/btr/btr0btr.c index 66aaa9d759face9d216a51f94ed9cc2fed057179..b3f7cc092dd66096b0b665e9f334fe789647fe97 100644 --- a/btr/btr0btr.c +++ b/btr/btr0btr.c @@ -592,13 +592,15 @@ an x-latch on the tree. @return rec_get_offsets() of the node pointer record */ static ulint* -btr_page_get_father_node_ptr( -/*=========================*/ +btr_page_get_father_node_ptr_func( +/*==============================*/ ulint* offsets,/*!< in: work area for the return value */ mem_heap_t* heap, /*!< in: memory heap to use */ btr_cur_t* cursor, /*!< in: cursor pointing to user record, out: cursor on node pointer record, its page x-latched */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { page_t* page; @@ -625,7 +627,8 @@ btr_page_get_father_node_ptr( tuple = dict_index_build_node_ptr(index, user_rec, 0, heap, level); btr_cur_search_to_nth_level(index, level + 1, tuple, PAGE_CUR_LE, - BTR_CONT_MODIFY_TREE, cursor, 0, mtr); + BTR_CONT_MODIFY_TREE, cursor, 0, + file, line, mtr); node_ptr = btr_cur_get_rec(cursor); ut_ad(!page_rec_is_comp(node_ptr) @@ -673,6 +676,9 @@ btr_page_get_father_node_ptr( return(offsets); } +#define btr_page_get_father_node_ptr(of,heap,cur,mtr) \ + btr_page_get_father_node_ptr_func(of,heap,cur,__FILE__,__LINE__,mtr) + /************************************************************//** Returns the upper level node pointer to a page. It is assumed that mtr holds an x-latch on the tree. @@ -1665,11 +1671,13 @@ Inserts a data tuple to a tree on a non-leaf level. It is assumed that mtr holds an x-latch on the tree. */ UNIV_INTERN void -btr_insert_on_non_leaf_level( -/*=========================*/ +btr_insert_on_non_leaf_level_func( +/*==============================*/ dict_index_t* index, /*!< in: index */ ulint level, /*!< in: level, must be > 0 */ dtuple_t* tuple, /*!< in: the record to be inserted */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { big_rec_t* dummy_big_rec; @@ -1681,7 +1689,7 @@ btr_insert_on_non_leaf_level( btr_cur_search_to_nth_level(index, level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE, - &cursor, 0, mtr); + &cursor, 0, file, line, mtr); err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG diff --git a/btr/btr0cur.c b/btr/btr0cur.c index 7cf9857578fc98024d9676e130f9472dfdccd8b3..67178af4d2a866ddaf9fcf88da8b5ac89447ebf8 100644 --- a/btr/btr0cur.c +++ b/btr/btr0cur.c @@ -352,6 +352,8 @@ btr_cur_search_to_nth_level( ulint has_search_latch,/*!< in: info on the latch mode the caller currently has on btr_search_latch: RW_S_LATCH, or 0 */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { page_t* page; @@ -589,7 +591,7 @@ btr_cur_search_to_nth_level( retry_page_get: block = buf_page_get_gen( space, zip_size, page_no, rw_latch, guess, buf_mode, - __FILE__, __LINE__, mtr); + file, line, mtr); if (block == NULL) { /* This must be a search to perform an insert/delete @@ -818,13 +820,15 @@ btr_cur_search_to_nth_level( Opens a cursor at either end of an index. */ UNIV_INTERN void -btr_cur_open_at_index_side( -/*=======================*/ +btr_cur_open_at_index_side_func( +/*============================*/ ibool from_left, /*!< in: TRUE if open to the low end, FALSE if to the high end */ dict_index_t* index, /*!< in: index */ ulint latch_mode, /*!< in: latch mode */ btr_cur_t* cursor, /*!< in: cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { page_cur_t* page_cursor; @@ -869,7 +873,7 @@ btr_cur_open_at_index_side( page_t* page; block = buf_page_get_gen(space, zip_size, page_no, RW_NO_LATCH, NULL, BUF_GET, - __FILE__, __LINE__, mtr); + file, line, mtr); page = buf_block_get_frame(block); ut_ad(0 == ut_dulint_cmp(index->id, btr_page_get_index_id(page))); @@ -949,11 +953,13 @@ btr_cur_open_at_index_side( Positions a cursor at a randomly chosen position within a B-tree. */ UNIV_INTERN void -btr_cur_open_at_rnd_pos( -/*====================*/ +btr_cur_open_at_rnd_pos_func( +/*=========================*/ dict_index_t* index, /*!< in: index */ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_cur_t* cursor, /*!< in/out: B-tree cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { page_cur_t* page_cursor; @@ -988,7 +994,7 @@ btr_cur_open_at_rnd_pos( block = buf_page_get_gen(space, zip_size, page_no, RW_NO_LATCH, NULL, BUF_GET, - __FILE__, __LINE__, mtr); + file, line, mtr); page = buf_block_get_frame(block); ut_ad(0 == ut_dulint_cmp(index->id, btr_page_get_index_id(page))); @@ -3242,7 +3248,8 @@ btr_estimate_n_rows_in_range( btr_cur_search_to_nth_level(index, 0, tuple1, mode1, BTR_SEARCH_LEAF | BTR_ESTIMATE, - &cursor, 0, &mtr); + &cursor, 0, + __FILE__, __LINE__, &mtr); } else { btr_cur_open_at_index_side(TRUE, index, BTR_SEARCH_LEAF | BTR_ESTIMATE, @@ -3259,7 +3266,8 @@ btr_estimate_n_rows_in_range( btr_cur_search_to_nth_level(index, 0, tuple2, mode2, BTR_SEARCH_LEAF | BTR_ESTIMATE, - &cursor, 0, &mtr); + &cursor, 0, + __FILE__, __LINE__, &mtr); } else { btr_cur_open_at_index_side(FALSE, index, BTR_SEARCH_LEAF | BTR_ESTIMATE, diff --git a/btr/btr0pcur.c b/btr/btr0pcur.c index ec98692c35b55e520fb4e272c3a234341dd4dcaf..436d1f252c31a8a72d2dd709667641fedbb4ca41 100644 --- a/btr/btr0pcur.c +++ b/btr/btr0pcur.c @@ -205,10 +205,12 @@ record and it can be restored on a user record whose ordering fields are identical to the ones of the original user record */ UNIV_INTERN ibool -btr_pcur_restore_position( -/*======================*/ +btr_pcur_restore_position_func( +/*===========================*/ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: detached persistent cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { dict_index_t* index; @@ -257,7 +259,8 @@ btr_pcur_restore_position( if (UNIV_LIKELY(buf_page_optimistic_get( latch_mode, cursor->block_when_stored, - cursor->modify_clock, mtr))) { + cursor->modify_clock, + file, line, mtr))) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; buf_block_dbg_add_level(btr_pcur_get_block(cursor), @@ -312,8 +315,8 @@ btr_pcur_restore_position( mode = PAGE_CUR_L; } - btr_pcur_open_with_no_init(index, tuple, mode, latch_mode, - cursor, 0, mtr); + btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, + cursor, 0, file, line, mtr); /* Restore the old search mode */ cursor->search_mode = old_mode; @@ -553,8 +556,8 @@ before first in tree. The latching mode must be BTR_SEARCH_LEAF or BTR_MODIFY_LEAF. */ UNIV_INTERN void -btr_pcur_open_on_user_rec( -/*======================*/ +btr_pcur_open_on_user_rec_func( +/*===========================*/ dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ ulint mode, /*!< in: PAGE_CUR_L, ... */ @@ -562,9 +565,12 @@ btr_pcur_open_on_user_rec( BTR_MODIFY_LEAF */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { - btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr); + btr_pcur_open_func(index, tuple, mode, latch_mode, cursor, + file, line, mtr); if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) { diff --git a/buf/buf0buf.c b/buf/buf0buf.c index 100f7ed20a765af96803af946d08d9fedd0ea341..c2022fba2a9b5e2c7e8f90f1cca930f662093a44 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -2430,8 +2430,8 @@ page. @return TRUE if success */ UNIV_INTERN ibool -buf_page_optimistic_get_func( -/*=========================*/ +buf_page_optimistic_get( +/*====================*/ ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */ buf_block_t* block, /*!< in: guessed buffer block */ ib_uint64_t modify_clock,/*!< in: modify clock value if mode is diff --git a/buf/buf0lru.c b/buf/buf0lru.c index d0dbce9979c304722bcec06edffea0e61e4f1e2a..0a21ca161a65a734eaf314b9b567123fa9dc48e0 100644 --- a/buf/buf0lru.c +++ b/buf/buf0lru.c @@ -350,17 +350,31 @@ buf_LRU_invalidate_tablespace( bpage = UT_LIST_GET_LAST(buf_pool->LRU); while (bpage != NULL) { - mutex_t* block_mutex = buf_page_get_mutex(bpage); buf_page_t* prev_bpage; + ibool prev_bpage_buf_fix = FALSE; ut_a(buf_page_in_file(bpage)); - mutex_enter(block_mutex); prev_bpage = UT_LIST_GET_PREV(LRU, bpage); - if (buf_page_get_space(bpage) == id) { - if (bpage->buf_fix_count > 0 - || buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + /* bpage->space and bpage->io_fix are protected by + buf_pool_mutex and block_mutex. It is safe to check + them while holding buf_pool_mutex only. */ + + if (buf_page_get_space(bpage) != id) { + /* Skip this block, as it does not belong to + the space that is being invalidated. */ + } else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + /* We cannot remove this page during this scan + yet; maybe the system is currently reading it + in, or flushing the modifications to the file */ + + all_freed = FALSE; + } else { + mutex_t* block_mutex = buf_page_get_mutex(bpage); + mutex_enter(block_mutex); + + if (bpage->buf_fix_count > 0) { /* We cannot remove this page during this scan yet; maybe the system is @@ -380,8 +394,40 @@ buf_LRU_invalidate_tablespace( (ulong) buf_page_get_page_no(bpage)); } #endif - if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE - && ((buf_block_t*) bpage)->is_hashed) { + if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { + /* This is a compressed-only block + descriptor. Ensure that prev_bpage + cannot be relocated when bpage is freed. */ + if (UNIV_LIKELY(prev_bpage != NULL)) { + switch (buf_page_get_state( + prev_bpage)) { + case BUF_BLOCK_FILE_PAGE: + /* Descriptors of uncompressed + blocks will not be relocated, + because we are holding the + buf_pool_mutex. */ + break; + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + /* Descriptors of compressed- + only blocks can be relocated, + unless they are buffer-fixed. + Because both bpage and + prev_bpage are protected by + buf_pool_zip_mutex, it is + not necessary to acquire + further mutexes. */ + ut_ad(&buf_pool_zip_mutex + == block_mutex); + ut_ad(mutex_own(block_mutex)); + prev_bpage_buf_fix = TRUE; + prev_bpage->buf_fix_count++; + break; + default: + ut_error; + } + } + } else if (((buf_block_t*) bpage)->is_hashed) { ulint page_no; ulint zip_size; @@ -405,7 +451,8 @@ buf_LRU_invalidate_tablespace( buf_flush_remove(bpage); } - /* Remove from the LRU list */ + /* Remove from the LRU list. */ + if (buf_LRU_block_remove_hashed_page(bpage, TRUE) != BUF_BLOCK_ZIP_FREE) { buf_LRU_block_free_hashed_page((buf_block_t*) @@ -417,18 +464,27 @@ buf_LRU_invalidate_tablespace( ut_ad(block_mutex == &buf_pool_zip_mutex); ut_ad(!mutex_own(block_mutex)); - /* The compressed block descriptor - (bpage) has been deallocated and - block_mutex released. Also, - buf_buddy_free() may have relocated - prev_bpage. Rescan the LRU list. */ + if (prev_bpage_buf_fix) { + /* We temporarily buffer-fixed + prev_bpage, so that + buf_buddy_free() could not + relocate it, in case it was a + compressed-only block + descriptor. */ + + mutex_enter(block_mutex); + ut_ad(prev_bpage->buf_fix_count > 0); + prev_bpage->buf_fix_count--; + mutex_exit(block_mutex); + } - bpage = UT_LIST_GET_LAST(buf_pool->LRU); - continue; + goto next_page_no_mutex; } - } next_page: - mutex_exit(block_mutex); + mutex_exit(block_mutex); + } + +next_page_no_mutex: bpage = prev_bpage; } diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 972430a5976830430875ec1c24f6ffad99d2b2ca..db63474501d70b19157e879a1ae51fce7f8cf106 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -2,6 +2,7 @@ Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. +Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -9,6 +10,13 @@ briefly in the InnoDB documentation. The contributions by Google are incorporated with their permission, and subject to the conditions contained in the file COPYING.Google. +Portions of this file contain modifications contributed and copyrighted +by Percona Inc.. Those modifications are +gratefully acknowledged and are described briefly in the InnoDB +documentation. The contributions by Percona Inc. are incorporated with +their permission, and subject to the conditions contained in the file +COPYING.Percona. + 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 Foundation; version 2 of the License. @@ -22,32 +30,6 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/*********************************************************************** - -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. -Copyright (c) 2009, Percona Inc. - -Portions of this file contain modifications contributed and copyrighted -by Percona Inc.. Those modifications are -gratefully acknowledged and are described briefly in the InnoDB -documentation. The contributions by Percona Inc. are incorporated with -their permission, and subject to the conditions contained in the file -COPYING.Percona. - -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 Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but -WITHOUT 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 - -***********************************************************************/ /* TODO list for the InnoDB handler in 5.0: - Remove the flag trx->active_trans and look at trx->conc_state @@ -3071,6 +3053,214 @@ innobase_get_int_col_max_value( return(max_value); } +/*******************************************************************//** +This function checks whether the index column information +is consistent between KEY info from mysql and that from innodb index. +@return TRUE if all column types match. */ +static +ibool +innobase_match_index_columns( +/*=========================*/ + const KEY* key_info, /*!< in: Index info + from mysql */ + const dict_index_t* index_info) /*!< in: Index info + from Innodb */ +{ + const KEY_PART_INFO* key_part; + const KEY_PART_INFO* key_end; + const dict_field_t* innodb_idx_fld; + const dict_field_t* innodb_idx_fld_end; + + DBUG_ENTER("innobase_match_index_columns"); + + /* Check whether user defined index column count matches */ + if (key_info->key_parts != index_info->n_user_defined_cols) { + DBUG_RETURN(FALSE); + } + + key_part = key_info->key_part; + key_end = key_part + key_info->key_parts; + innodb_idx_fld = index_info->fields; + innodb_idx_fld_end = index_info->fields + index_info->n_fields; + + /* Check each index column's datatype. We do not check + column name because there exists case that index + column name got modified in mysql but such change does not + propagate to InnoDB. + One hidden assumption here is that the index column sequences + are matched up between those in mysql and Innodb. */ + for (; key_part != key_end; ++key_part) { + ulint col_type; + ibool is_unsigned; + ulint mtype = innodb_idx_fld->col->mtype; + + /* Need to translate to InnoDB column type before + comparison. */ + col_type = get_innobase_type_from_mysql_type(&is_unsigned, + key_part->field); + + /* Ignore Innodb specific system columns. */ + while (mtype == DATA_SYS) { + innodb_idx_fld++; + + if (innodb_idx_fld >= innodb_idx_fld_end) { + DBUG_RETURN(FALSE); + } + } + + if (col_type != mtype) { + /* Column Type mismatches */ + DBUG_RETURN(FALSE); + } + + innodb_idx_fld++; + } + + DBUG_RETURN(TRUE); +} + +/*******************************************************************//** +This function builds a translation table in INNOBASE_SHARE +structure for fast index location with mysql array number from its +table->key_info structure. This also provides the necessary translation +between the key order in mysql key_info and Innodb ib_table->indexes if +they are not fully matched with each other. +Note we do not have any mutex protecting the translation table +building based on the assumption that there is no concurrent +index creation/drop and DMLs that requires index lookup. All table +handle will be closed before the index creation/drop. +@return TRUE if index translation table built successfully */ +static +ibool +innobase_build_index_translation( +/*=============================*/ + const TABLE* table, /*!< in: table in MySQL data + dictionary */ + dict_table_t* ib_table, /*!< in: table in Innodb data + dictionary */ + INNOBASE_SHARE* share) /*!< in/out: share structure + where index translation table + will be constructed in. */ +{ + ulint mysql_num_index; + ulint ib_num_index; + dict_index_t** index_mapping; + ibool ret = TRUE; + + DBUG_ENTER("innobase_build_index_translation"); + + mysql_num_index = table->s->keys; + ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); + + index_mapping = share->idx_trans_tbl.index_mapping; + + /* If there exists inconsistency between MySQL and InnoDB dictionary + (metadata) information, the number of index defined in MySQL + could exceed that in InnoDB, do not build index translation + table in such case */ + if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) { + ret = FALSE; + goto func_exit; + } + + /* If index entry count is non-zero, nothing has + changed since last update, directly return TRUE */ + if (share->idx_trans_tbl.index_count) { + /* Index entry count should still match mysql_num_index */ + ut_a(share->idx_trans_tbl.index_count == mysql_num_index); + goto func_exit; + } + + /* The number of index increased, rebuild the mapping table */ + if (mysql_num_index > share->idx_trans_tbl.array_size) { + index_mapping = (dict_index_t**) my_realloc(index_mapping, + mysql_num_index * + sizeof(*index_mapping), + MYF(MY_ALLOW_ZERO_PTR)); + + if (!index_mapping) { + ret = FALSE; + goto func_exit; + } + + share->idx_trans_tbl.array_size = mysql_num_index; + } + + + /* For each index in the mysql key_info array, fetch its + corresponding InnoDB index pointer into index_mapping + array. */ + for (ulint count = 0; count < mysql_num_index; count++) { + + /* Fetch index pointers into index_mapping according to mysql + index sequence */ + index_mapping[count] = dict_table_get_index_on_name( + ib_table, table->key_info[count].name); + + if (!index_mapping[count]) { + sql_print_error("Cannot find index %s in InnoDB " + "index dictionary.", + table->key_info[count].name); + ret = FALSE; + goto func_exit; + } + + /* Double check fetched index has the same + column info as those in mysql key_info. */ + if (!innobase_match_index_columns(&table->key_info[count], + index_mapping[count])) { + sql_print_error("Found index %s whose column info " + "does not match that of MySQL.", + table->key_info[count].name); + ret = FALSE; + goto func_exit; + } + } + + /* Successfully built the translation table */ + share->idx_trans_tbl.index_count = mysql_num_index; + +func_exit: + if (!ret) { + /* Build translation table failed. */ + my_free(index_mapping, MYF(MY_ALLOW_ZERO_PTR)); + + share->idx_trans_tbl.array_size = 0; + share->idx_trans_tbl.index_count = 0; + index_mapping = NULL; + } + + share->idx_trans_tbl.index_mapping = index_mapping; + + DBUG_RETURN(ret); +} + +/*******************************************************************//** +This function uses index translation table to quickly locate the +requested index structure. +Note we do not have mutex protection for the index translatoin table +access, it is based on the assumption that there is no concurrent +translation table rebuild (fter create/drop index) and DMLs that +require index lookup. +@return dict_index_t structure for requested index. NULL if +fail to locate the index structure. */ +static +dict_index_t* +innobase_index_lookup( +/*==================*/ + INNOBASE_SHARE* share, /*!< in: share structure for index + translation table. */ + uint keynr) /*!< in: index number for the requested + index */ +{ + if (!share->idx_trans_tbl.index_mapping + || keynr >= share->idx_trans_tbl.index_count) { + return(NULL); + } + + return(share->idx_trans_tbl.index_mapping[keynr]); +} + /************************************************************************ Set the autoinc column max value. This should only be called once from ha_innobase::open(). Therefore there's no need for a covering lock. */ @@ -3086,9 +3276,9 @@ ha_innobase::innobase_initialize_autoinc() auto_inc = innobase_get_int_col_max_value(field); } else { /* We have no idea what's been passed in to us as the - autoinc column. We set it to the MAX_INT of our table - autoinc type. */ - auto_inc = 0xFFFFFFFFFFFFFFFFULL; + autoinc column. We set it to the 0, effectively disabling + updates to the table. */ + auto_inc = 0; ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Unable to determine the AUTOINC " @@ -3097,7 +3287,7 @@ ha_innobase::innobase_initialize_autoinc() if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { /* If the recovery level is set so high that writes - are disabled we force the AUTOINC counter to the MAX + are disabled we force the AUTOINC counter to 0 value effectively disabling writes to the table. Secondly, we avoid reading the table in case the read results in failure due to a corrupted table/index. @@ -3106,7 +3296,10 @@ ha_innobase::innobase_initialize_autoinc() tables can be dumped with minimal hassle. If an error were returned in this case, the first attempt to read the table would fail and subsequent SELECTs would succeed. */ + auto_inc = 0; } else if (field == NULL) { + /* This is a far more serious error, best to avoid + opening the table and return failure. */ my_error(ER_AUTOINC_READ_FAILED, MYF(0)); } else { dict_index_t* index; @@ -3135,7 +3328,7 @@ ha_innobase::innobase_initialize_autoinc() "InnoDB: Unable to find the AUTOINC column " "%s in the InnoDB table %s.\n" "InnoDB: We set the next AUTOINC column " - "value to the maximum possible value,\n" + "value to 0,\n" "InnoDB: in effect disabling the AUTOINC " "next value generation.\n" "InnoDB: You can either set the next " @@ -3144,7 +3337,13 @@ ha_innobase::innobase_initialize_autoinc() "recreating the table.\n", col_name, index->table->name); - my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + /* This will disable the AUTOINC generation. */ + auto_inc = 0; + + /* We want the open to succeed, so that the user can + take corrective action. ie. reads should succeed but + updates should fail. */ + err = DB_SUCCESS; break; default: /* row_search_max_autoinc() should only return @@ -3287,6 +3486,11 @@ ha_innobase::open( primary_key = table->s->primary_key; key_used_on_scan = primary_key; + if (!innobase_build_index_translation(table, ib_table, share)) { + sql_print_error("Build InnoDB index translation table for" + " Table %s failed", name); + } + /* Allocate a buffer for a 'row reference'. A row reference is a string of bytes of length ref_length which uniquely specifies a row in our table. Note that MySQL may also compare two row @@ -4409,11 +4613,17 @@ ha_innobase::write_row( prebuilt->autoinc_error = DB_SUCCESS; if ((error = update_auto_increment())) { - /* We don't want to mask autoinc overflow errors. */ - if (prebuilt->autoinc_error != DB_SUCCESS) { - error = (int) prebuilt->autoinc_error; + /* Handle the case where the AUTOINC sub-system + failed during initialization. */ + if (prebuilt->autoinc_error == DB_UNSUPPORTED) { + error_result = ER_AUTOINC_READ_FAILED; + /* Set the error message to report too. */ + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + goto func_exit; + } else if (prebuilt->autoinc_error != DB_SUCCESS) { + error = (int) prebuilt->autoinc_error; goto report_error; } @@ -5202,8 +5412,27 @@ ha_innobase::innobase_get_index( if (keynr != MAX_KEY && table->s->keys > 0) { key = table->key_info + keynr; - index = dict_table_get_index_on_name(prebuilt->table, - key->name); + index = innobase_index_lookup(share, keynr); + + if (index) { + ut_a(ut_strcmp(index->name, key->name) == 0); + } else { + /* Can't find index with keynr in the translation + table. Only print message if the index translation + table exists */ + if (share->idx_trans_tbl.index_mapping) { + sql_print_error("InnoDB could not find " + "index %s key no %u for " + "table %s through its " + "index translation table", + key ? key->name : "NULL", + keynr, + prebuilt->table->name); + } + + index = dict_table_get_index_on_name(prebuilt->table, + key->name); + } } else { index = dict_table_get_first_index(prebuilt->table); } @@ -5264,7 +5493,7 @@ ha_innobase::change_active_index( dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields); dict_index_copy_types(prebuilt->search_tuple, prebuilt->index, - prebuilt->index->n_fields); + prebuilt->index->n_fields); /* MySQL changes the active index for a handle also during some queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX() @@ -6894,10 +7123,15 @@ ha_innobase::records_in_range( key = table->key_info + active_index; - index = dict_table_get_index_on_name(prebuilt->table, key->name); + index = innobase_get_index(keynr); - /* MySQL knows about this index and so we must be able to find it.*/ - ut_a(index); + /* There exists possibility of not being able to find requested + index due to inconsistency between MySQL and InoDB dictionary info. + Necessary message should have been printed in innobase_get_index() */ + if (UNIV_UNLIKELY(!index)) { + n_rows = HA_POS_ERROR; + goto func_exit; + } heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t) + sizeof(dtuple_t))); @@ -6942,6 +7176,7 @@ ha_innobase::records_in_range( mem_heap_free(heap); +func_exit: my_free(key_val_buff2, MYF(0)); prebuilt->trx->op_info = (char*)""; @@ -7083,6 +7318,7 @@ ha_innobase::info( char path[FN_REFLEN]; os_file_stat_t stat_info; + DBUG_ENTER("info"); /* If we are forcing recovery at a high level, we will suppress @@ -7243,13 +7479,29 @@ ha_innobase::info( } if (flag & HA_STATUS_CONST) { - index = dict_table_get_first_index(ib_table); + /* Verify the number of index in InnoDB and MySQL + matches up. If prebuilt->clust_index_was_generated + holds, InnoDB defines GEN_CLUST_INDEX internally */ + ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) + - prebuilt->clust_index_was_generated; - if (prebuilt->clust_index_was_generated) { - index = dict_table_get_next_index(index); + if (table->s->keys != num_innodb_index) { + sql_print_error("Table %s contains %lu " + "indexes inside InnoDB, which " + "is different from the number of " + "indexes %u defined in the MySQL ", + ib_table->name, num_innodb_index, + table->s->keys); } for (i = 0; i < table->s->keys; i++) { + /* We could get index quickly through internal + index mapping with the index translation table. + The identity of index (match up index name with + that of table->key_info[i]) is already verified in + innobase_get_index(). */ + index = innobase_get_index(i); + if (index == NULL) { sql_print_error("Table %s contains fewer " "indexes inside InnoDB than " @@ -7301,8 +7553,6 @@ ha_innobase::info( rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 : (ulong) rec_per_key; } - - index = dict_table_get_next_index(index); } } @@ -7380,8 +7630,13 @@ ha_innobase::check( HA_CHECK_OPT* check_opt) /*!< in: check options, currently ignored */ { - ulint ret; + dict_index_t* index; + ulint n_rows; + ulint n_rows_in_table = ULINT_UNDEFINED; + ibool is_ok = TRUE; + ulint old_isolation_level; + DBUG_ENTER("ha_innobase::check"); DBUG_ASSERT(thd == ha_thd()); ut_a(prebuilt->trx); ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N); @@ -7394,17 +7649,140 @@ ha_innobase::check( build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW); } - ret = row_check_table_for_mysql(prebuilt); + if (prebuilt->table->ibd_file_missing) { + sql_print_error("InnoDB: Error:\n" + "InnoDB: MySQL is trying to use a table handle" + " but the .ibd file for\n" + "InnoDB: table %s does not exist.\n" + "InnoDB: Have you deleted the .ibd file" + " from the database directory under\n" + "InnoDB: the MySQL datadir, or have you" + " used DISCARD TABLESPACE?\n" + "InnoDB: Please refer to\n" + "InnoDB: " REFMAN "innodb-troubleshooting.html\n" + "InnoDB: how you can resolve the problem.\n", + prebuilt->table->name); + DBUG_RETURN(HA_ADMIN_CORRUPT); + } + + prebuilt->trx->op_info = "checking table"; - switch (ret) { - case DB_SUCCESS: - return(HA_ADMIN_OK); - case DB_INTERRUPTED: + old_isolation_level = prebuilt->trx->isolation_level; + + /* We must run the index record counts at an isolation level + >= READ COMMITTED, because a dirty read can see a wrong number + of records in some index; to play safe, we use always + REPEATABLE READ here */ + + prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; + + /* Enlarge the fatal lock wait timeout during CHECK TABLE. */ + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + + for (index = dict_table_get_first_index(prebuilt->table); + index != NULL; + index = dict_table_get_next_index(index)) { +#if 0 + fputs("Validating index ", stderr); + ut_print_name(stderr, trx, FALSE, index->name); + putc('\n', stderr); +#endif + + if (!btr_validate_index(index, prebuilt->trx)) { + is_ok = FALSE; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NOT_KEYFILE, + "InnoDB: The B-tree of" + " index '%-.200s' is corrupted.", + index->name); + continue; + } + + /* Instead of invoking change_active_index(), set up + a dummy template for non-locking reads, disabling + access to the clustered index. */ + prebuilt->index = index; + + prebuilt->index_usable = row_merge_is_index_usable( + prebuilt->trx, prebuilt->index); + + if (UNIV_UNLIKELY(!prebuilt->index_usable)) { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_TABLE_DEF_CHANGED, + "InnoDB: Insufficient history for" + " index '%-.200s'", + index->name); + continue; + } + + prebuilt->sql_stat_start = TRUE; + prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE; + prebuilt->n_template = 0; + prebuilt->need_to_access_clustered = FALSE; + + dtuple_set_n_fields(prebuilt->search_tuple, 0); + + prebuilt->select_lock_type = LOCK_NONE; + + if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NOT_KEYFILE, + "InnoDB: The B-tree of" + " index '%-.200s' is corrupted.", + index->name); + is_ok = FALSE; + } + + if (thd_killed(user_thd)) { + break; + } + +#if 0 + fprintf(stderr, "%lu entries in index %s\n", n_rows, + index->name); +#endif + + if (index == dict_table_get_first_index(prebuilt->table)) { + n_rows_in_table = n_rows; + } else if (n_rows != n_rows_in_table) { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NOT_KEYFILE, + "InnoDB: Index '%-.200s'" + " contains %lu entries," + " should be %lu.", + index->name, + (ulong) n_rows, + (ulong) n_rows_in_table); + is_ok = FALSE; + } + } + + /* Restore the original isolation level */ + prebuilt->trx->isolation_level = old_isolation_level; + + /* We validate also the whole adaptive hash index for all tables + at every CHECK TABLE */ + + if (!btr_search_validate()) { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NOT_KEYFILE, + "InnoDB: The adaptive hash index is corrupted."); + is_ok = FALSE; + } + + /* Restore the fatal lock wait timeout after CHECK TABLE. */ + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + + prebuilt->trx->op_info = ""; + if (thd_killed(user_thd)) { my_error(ER_QUERY_INTERRUPTED, MYF(0)); - return(-1); - default: - return(HA_ADMIN_CORRUPT); } + + DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT); } /*************************************************************//** @@ -8466,6 +8844,11 @@ static INNOBASE_SHARE* get_share(const char* table_name) innobase_open_tables, fold, share); thr_lock_init(&share->lock); + + /* Index translation table initialization */ + share->idx_trans_tbl.index_mapping = NULL; + share->idx_trans_tbl.index_count = 0; + share->idx_trans_tbl.array_size = 0; } share->use_count++; @@ -8496,6 +8879,11 @@ static void free_share(INNOBASE_SHARE* share) HASH_DELETE(INNOBASE_SHARE, table_name_hash, innobase_open_tables, fold, share); thr_lock_delete(&share->lock); + + /* Free any memory from index translation table */ + my_free(share->idx_trans_tbl.index_mapping, + MYF(MY_ALLOW_ZERO_PTR)); + my_free(share, MYF(0)); /* TODO: invoke HASH_MIGRATE if innobase_open_tables @@ -8730,7 +9118,10 @@ ha_innobase::innobase_get_autoinc( *value = dict_table_autoinc_read(prebuilt->table); /* It should have been initialized during open. */ - ut_a(*value != 0); + if (*value == 0) { + prebuilt->autoinc_error = DB_UNSUPPORTED; + dict_table_autoinc_unlock(prebuilt->table); + } } return(prebuilt->autoinc_error); @@ -8810,6 +9201,11 @@ ha_innobase::get_auto_increment( invoking this method. So we are not sure if it's guaranteed to be 0 or not. */ + /* We need the upper limit of the col type to check for + whether we update the table autoinc counter or not. */ + ulonglong col_max_value = innobase_get_int_col_max_value( + table->next_number_field); + /* Called for the first time ? */ if (trx->n_autoinc_rows == 0) { @@ -8826,6 +9222,11 @@ ha_innobase::get_auto_increment( /* Not in the middle of a mult-row INSERT. */ } else if (prebuilt->autoinc_last_value == 0) { set_if_bigger(*first_value, autoinc); + /* Check for -ve values. */ + } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) { + /* Set to next logical value. */ + ut_a(autoinc > trx->n_autoinc_rows); + *first_value = (autoinc - trx->n_autoinc_rows) - 1; } *nb_reserved_values = trx->n_autoinc_rows; @@ -8836,12 +9237,6 @@ ha_innobase::get_auto_increment( ulonglong need; ulonglong current; ulonglong next_value; - ulonglong col_max_value; - - /* We need the upper limit of the col type to check for - whether we update the table autoinc counter or not. */ - col_max_value = innobase_get_int_col_max_value( - table->next_number_field); current = *first_value > col_max_value ? autoinc : *first_value; need = *nb_reserved_values * increment; diff --git a/handler/ha_innodb.h b/handler/ha_innodb.h index 0e366a1eb2c491dad5f4adbc24c3cffb87bc037e..5dd9726ae4cc90e0ebded8c52abd5d86506eb29f 100644 --- a/handler/ha_innodb.h +++ b/handler/ha_innodb.h @@ -27,15 +27,31 @@ Place, Suite 330, Boston, MA 02111-1307 USA #pragma interface /* gcc class implementation */ #endif +/* Structure defines translation table between mysql index and innodb +index structures */ +typedef struct innodb_idx_translate_struct { + ulint index_count; /*!< number of valid index entries + in the index_mapping array */ + ulint array_size; /*!< array size of index_mapping */ + dict_index_t** index_mapping; /*!< index pointer array directly + maps to index in Innodb from MySQL + array index */ +} innodb_idx_translate_t; + + /** InnoDB table share */ typedef struct st_innobase_share { - THR_LOCK lock; /*!< MySQL lock protecting - this structure */ - const char* table_name; /*!< InnoDB table name */ - uint use_count; /*!< reference count, - incremented in get_share() - and decremented in free_share() */ - void* table_name_hash;/*!< hash table chain node */ + THR_LOCK lock; /*!< MySQL lock protecting + this structure */ + const char* table_name; /*!< InnoDB table name */ + uint use_count; /*!< reference count, + incremented in get_share() + and decremented in + free_share() */ + void* table_name_hash;/*!< hash table chain node */ + innodb_idx_translate_t idx_trans_tbl; /*!< index translation + table between MySQL and + Innodb */ } INNOBASE_SHARE; diff --git a/handler/handler0alter.cc b/handler/handler0alter.cc index a5008991400fe7f174ec96a4773bd611b9b09435..47999ae37f8e0ed3db900b9d8e1b54f93e2c203a 100644 --- a/handler/handler0alter.cc +++ b/handler/handler0alter.cc @@ -764,6 +764,10 @@ ha_innobase::add_index( ut_ad(error == DB_SUCCESS); + /* We will need to rebuild index translation table. Set + valid index entry count in the translation table to zero */ + share->idx_trans_tbl.index_count = 0; + /* Commit the data dictionary transaction in order to release the table locks on the system tables. This means that if MySQL crashes while creating a new primary key inside @@ -1198,6 +1202,10 @@ ha_innobase::final_drop_index( ut_a(!index->to_be_dropped); } + /* We will need to rebuild index translation table. Set + valid index entry count in the translation table to zero */ + share->idx_trans_tbl.index_count = 0; + #ifdef UNIV_DEBUG dict_table_check_for_dup_indexes(prebuilt->table); #endif diff --git a/include/btr0btr.h b/include/btr0btr.h index aa51490ab19d59dc9800ce9e6eebeb0778f8b058..5af5d0c49f0fb7a1c857f78b1bfab2ec7d975e9d 100644 --- a/include/btr0btr.h +++ b/include/btr0btr.h @@ -327,12 +327,16 @@ Inserts a data tuple to a tree on a non-leaf level. It is assumed that mtr holds an x-latch on the tree. */ UNIV_INTERN void -btr_insert_on_non_leaf_level( -/*=========================*/ +btr_insert_on_non_leaf_level_func( +/*==============================*/ dict_index_t* index, /*!< in: index */ ulint level, /*!< in: level, must be > 0 */ dtuple_t* tuple, /*!< in: the record to be inserted */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +# define btr_insert_on_non_leaf_level(i,l,t,m) \ + btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m) #endif /* !UNIV_HOTBACKUP */ /****************************************************************//** Sets a record as the predefined minimum record. */ diff --git a/include/btr0cur.h b/include/btr0cur.h index a7984005ba3085922841939fdb2332e18ad86b32..2db38f2fa96b11aff901a26dc77c562c26200601 100644 --- a/include/btr0cur.h +++ b/include/btr0cur.h @@ -152,29 +152,39 @@ btr_cur_search_to_nth_level( ulint has_search_latch,/*!< in: latch mode the caller currently has on btr_search_latch: RW_S_LATCH, or 0 */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ /*****************************************************************//** Opens a cursor at either end of an index. */ UNIV_INTERN void -btr_cur_open_at_index_side( -/*=======================*/ +btr_cur_open_at_index_side_func( +/*============================*/ ibool from_left, /*!< in: TRUE if open to the low end, FALSE if to the high end */ dict_index_t* index, /*!< in: index */ ulint latch_mode, /*!< in: latch mode */ btr_cur_t* cursor, /*!< in: cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_cur_open_at_index_side(f,i,l,c,m) \ + btr_cur_open_at_index_side_func(f,i,l,c,__FILE__,__LINE__,m) /**********************************************************************//** Positions a cursor at a randomly chosen position within a B-tree. */ UNIV_INTERN void -btr_cur_open_at_rnd_pos( -/*====================*/ +btr_cur_open_at_rnd_pos_func( +/*=========================*/ dict_index_t* index, /*!< in: index */ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_cur_t* cursor, /*!< in/out: B-tree cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_cur_open_at_rnd_pos(i,l,c,m) \ + btr_cur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m) /*************************************************************//** Tries to perform an insert to a page in an index tree, next to cursor. It is assumed that mtr holds an x-latch on the page. The operation does diff --git a/include/btr0pcur.h b/include/btr0pcur.h index 12b1375d8b7cac79da136250c3f03777753701ad..7d8bac85f3ec6a6d0011392bb33dc24862538073 100644 --- a/include/btr0pcur.h +++ b/include/btr0pcur.h @@ -82,8 +82,8 @@ Initializes and opens a persistent cursor to an index tree. It should be closed with btr_pcur_close. */ UNIV_INLINE void -btr_pcur_open( -/*==========*/ +btr_pcur_open_func( +/*===============*/ dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ ulint mode, /*!< in: PAGE_CUR_L, ...; @@ -94,14 +94,18 @@ btr_pcur_open( record! */ ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_pcur_open(i,t,md,l,c,m) \ + btr_pcur_open_func(i,t,md,l,c,__FILE__,__LINE__,m) /**************************************************************//** Opens an persistent cursor to an index tree without initializing the cursor. */ UNIV_INLINE void -btr_pcur_open_with_no_init( -/*=======================*/ +btr_pcur_open_with_no_init_func( +/*============================*/ dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ ulint mode, /*!< in: PAGE_CUR_L, ...; @@ -119,7 +123,12 @@ btr_pcur_open_with_no_init( ulint has_search_latch,/*!< in: latch mode the caller currently has on btr_search_latch: RW_S_LATCH, or 0 */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \ + btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m) + /*****************************************************************//** Opens a persistent cursor at either end of an index. */ UNIV_INLINE @@ -160,8 +169,8 @@ before first in tree. The latching mode must be BTR_SEARCH_LEAF or BTR_MODIFY_LEAF. */ UNIV_INTERN void -btr_pcur_open_on_user_rec( -/*======================*/ +btr_pcur_open_on_user_rec_func( +/*===========================*/ dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ ulint mode, /*!< in: PAGE_CUR_L, ... */ @@ -169,17 +178,25 @@ btr_pcur_open_on_user_rec( BTR_MODIFY_LEAF */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_pcur_open_on_user_rec(i,t,md,l,c,m) \ + btr_pcur_open_on_user_rec_func(i,t,md,l,c,__FILE__,__LINE__,m) /**********************************************************************//** Positions a cursor at a randomly chosen position within a B-tree. */ UNIV_INLINE void -btr_pcur_open_at_rnd_pos( -/*=====================*/ +btr_pcur_open_at_rnd_pos_func( +/*==========================*/ dict_index_t* index, /*!< in: index */ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in/out: B-tree pcur */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_pcur_open_at_rnd_pos(i,l,c,m) \ + btr_pcur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m) /**************************************************************//** Frees the possible old_rec_buf buffer of a persistent cursor and sets the latch mode of the persistent cursor to BTR_NO_LATCHES. */ @@ -218,11 +235,15 @@ record and it can be restored on a user record whose ordering fields are identical to the ones of the original user record */ UNIV_INTERN ibool -btr_pcur_restore_position( -/*======================*/ +btr_pcur_restore_position_func( +/*===========================*/ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: detached persistent cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr); /*!< in: mtr */ +#define btr_pcur_restore_position(l,cur,mtr) \ + btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr) /**************************************************************//** If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY, releases the page latch and bufferfix reserved by the cursor. diff --git a/include/btr0pcur.ic b/include/btr0pcur.ic index 0ca7223f86193e0bf99c3cdffb95d0acd1e6baa6..b11d7dce21c84bfa3db1314c56fb40f37a8e9560 100644 --- a/include/btr0pcur.ic +++ b/include/btr0pcur.ic @@ -483,8 +483,8 @@ Initializes and opens a persistent cursor to an index tree. It should be closed with btr_pcur_close. */ UNIV_INLINE void -btr_pcur_open( -/*==========*/ +btr_pcur_open_func( +/*===============*/ dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ ulint mode, /*!< in: PAGE_CUR_L, ...; @@ -495,6 +495,8 @@ btr_pcur_open( record! */ ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { btr_cur_t* btr_cursor; @@ -511,7 +513,7 @@ btr_pcur_open( btr_cursor = btr_pcur_get_btr_cur(cursor); btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, - btr_cursor, 0, mtr); + btr_cursor, 0, file, line, mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->trx_if_known = NULL; @@ -522,8 +524,8 @@ Opens an persistent cursor to an index tree without initializing the cursor. */ UNIV_INLINE void -btr_pcur_open_with_no_init( -/*=======================*/ +btr_pcur_open_with_no_init_func( +/*============================*/ dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ ulint mode, /*!< in: PAGE_CUR_L, ...; @@ -541,6 +543,8 @@ btr_pcur_open_with_no_init( ulint has_search_latch,/*!< in: latch mode the caller currently has on btr_search_latch: RW_S_LATCH, or 0 */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { btr_cur_t* btr_cursor; @@ -553,7 +557,8 @@ btr_pcur_open_with_no_init( btr_cursor = btr_pcur_get_btr_cur(cursor); btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, - btr_cursor, has_search_latch, mtr); + btr_cursor, has_search_latch, + file, line, mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; @@ -600,11 +605,13 @@ btr_pcur_open_at_index_side( Positions a cursor at a randomly chosen position within a B-tree. */ UNIV_INLINE void -btr_pcur_open_at_rnd_pos( -/*=====================*/ +btr_pcur_open_at_rnd_pos_func( +/*==========================*/ dict_index_t* index, /*!< in: index */ ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in/out: B-tree pcur */ + const char* file, /*!< in: file name */ + ulint line, /*!< in: line where called */ mtr_t* mtr) /*!< in: mtr */ { /* Initialize the cursor */ @@ -614,8 +621,9 @@ btr_pcur_open_at_rnd_pos( btr_pcur_init(cursor); - btr_cur_open_at_rnd_pos(index, latch_mode, - btr_pcur_get_btr_cur(cursor), mtr); + btr_cur_open_at_rnd_pos_func(index, latch_mode, + btr_pcur_get_btr_cur(cursor), + file, line, mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; diff --git a/include/buf0buf.h b/include/buf0buf.h index bc7555dbb6c740cc4d88999fa261d4c0beb605b3..082022e2fe2fe259e4320c8cd6599af5cd55aa75 100644 --- a/include/buf0buf.h +++ b/include/buf0buf.h @@ -207,20 +207,14 @@ with care. */ #define buf_page_get_with_no_latch(SP, ZS, OF, MTR) buf_page_get_gen(\ SP, ZS, OF, RW_NO_LATCH, NULL,\ BUF_GET_NO_LATCH, __FILE__, __LINE__, MTR) -/**************************************************************//** -NOTE! The following macros should be used instead of -buf_page_optimistic_get_func, to improve debugging. Only values RW_S_LATCH and -RW_X_LATCH are allowed as LA! */ -#define buf_page_optimistic_get(LA, BL, MC, MTR) \ - buf_page_optimistic_get_func(LA, BL, MC, __FILE__, __LINE__, MTR) /********************************************************************//** This is the general function used to get optimistic access to a database page. @return TRUE if success */ UNIV_INTERN ibool -buf_page_optimistic_get_func( -/*=========================*/ +buf_page_optimistic_get( +/*====================*/ ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */ buf_block_t* block, /*!< in: guessed block */ ib_uint64_t modify_clock,/*!< in: modify clock value if mode is diff --git a/include/log0log.h b/include/log0log.h index 233714eb63a1174d7c95a86f922dec9e0abd0abe..7fc24b58e4c40f1e3510efe24a90e064ed179191 100644 --- a/include/log0log.h +++ b/include/log0log.h @@ -1,22 +1,5 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -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 - -*****************************************************************************/ -/***************************************************************************** - Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. Copyright (c) 2009, Google Inc. diff --git a/include/os0file.h b/include/os0file.h index f76a1d196c688265cca862777fcbf7043453da31..1f2ce3624dc32727c4eb3d8c3feb99987299205e 100644 --- a/include/os0file.h +++ b/include/os0file.h @@ -1,20 +1,3 @@ -/***************************************************************************** - -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -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 - -*****************************************************************************/ /*********************************************************************** Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. diff --git a/include/row0mysql.h b/include/row0mysql.h index b05241f00f8d9d73820b86213867cf79c4ae7fad..03b29fd6538c9c0459e39519c43125be28c2957f 100644 --- a/include/row0mysql.h +++ b/include/row0mysql.h @@ -451,6 +451,12 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: transaction handle */ ibool drop_db);/*!< in: TRUE=dropping whole database */ +/*********************************************************************//** +Drop all temporary tables during crash recovery. */ +UNIV_INTERN +void +row_mysql_drop_temp_tables(void); +/*============================*/ /*********************************************************************//** Discards the tablespace of a table which stored in an .ibd file. Discarding @@ -494,14 +500,19 @@ row_rename_table_for_mysql( trx_t* trx, /*!< in: transaction handle */ ibool commit); /*!< in: if TRUE then commit trx */ /*********************************************************************//** -Checks a table for corruption. -@return DB_ERROR or DB_SUCCESS */ +Checks that the index contains entries in an ascending order, unique +constraint is not broken, and calculates the number of index entries +in the read view of the current transaction. +@return DB_SUCCESS if ok */ UNIV_INTERN ulint -row_check_table_for_mysql( +row_check_index_for_mysql( /*======================*/ - row_prebuilt_t* prebuilt); /*!< in: prebuilt struct in MySQL - handle */ + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct + in MySQL handle */ + const dict_index_t* index, /*!< in: index */ + ulint* n_rows); /*!< out: number of entries + seen in the consistent read */ /*********************************************************************//** Determines if a table is a magic monitor table. diff --git a/include/srv0srv.h b/include/srv0srv.h index 5b4295dceadc9cad886cea7b8086426a74e12bb1..ae66772b25ace622d452fd4109efbb8214cd02d6 100644 --- a/include/srv0srv.h +++ b/include/srv0srv.h @@ -2,6 +2,7 @@ Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. Copyright (c) 2008, 2009, Google Inc. +Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -9,6 +10,13 @@ briefly in the InnoDB documentation. The contributions by Google are incorporated with their permission, and subject to the conditions contained in the file COPYING.Google. +Portions of this file contain modifications contributed and copyrighted +by Percona Inc.. Those modifications are +gratefully acknowledged and are described briefly in the InnoDB +documentation. The contributions by Percona Inc. are incorporated with +their permission, and subject to the conditions contained in the file +COPYING.Percona. + 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 Foundation; version 2 of the License. @@ -22,32 +30,6 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/*********************************************************************** - -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. -Copyright (c) 2009, Percona Inc. - -Portions of this file contain modifications contributed and copyrighted -by Percona Inc.. Those modifications are -gratefully acknowledged and are described briefly in the InnoDB -documentation. The contributions by Percona Inc. are incorporated with -their permission, and subject to the conditions contained in the file -COPYING.Percona. - -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 Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but -WITHOUT 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 - -***********************************************************************/ /**************************************************//** @file include/srv0srv.h diff --git a/include/trx0trx.h b/include/trx0trx.h index 5f2c1246f37f15e3ae5b3df201eb00e984897d35..e2ad1f2f722c00ea6788ba7f62cd45e10cbcae6b 100644 --- a/include/trx0trx.h +++ b/include/trx0trx.h @@ -526,6 +526,9 @@ struct trx_struct{ /* 0, RW_S_LATCH, or RW_X_LATCH: the latch mode trx currently holds on dict_operation_lock */ + unsigned deadlock_mark:1;/*!< a mark field used in deadlock + checking algorithm. Always protected + by the kernel_mutex. */ time_t start_time; /*!< time the trx object was created or the state last time became TRX_ACTIVE */ @@ -640,11 +643,6 @@ struct trx_struct{ wait_thrs; /*!< query threads belonging to this trx that are in the QUE_THR_LOCK_WAIT state */ - ulint deadlock_mark; /*!< a mark field used in deadlock - checking algorithm. This must be - in its own machine word, because - it can be changed by other - threads while holding kernel_mutex. */ /*------------------------------*/ mem_heap_t* lock_heap; /*!< memory heap for the locks of the transaction */ diff --git a/lock/lock0lock.c b/lock/lock0lock.c index 0fa67d31716bc972d682c8d4ac2b0eaf87153be3..11a5232b0dc1be42566aa922aebb184095f6d251 100644 --- a/lock/lock0lock.c +++ b/lock/lock0lock.c @@ -401,7 +401,7 @@ lock_deadlock_recursive( /*====================*/ trx_t* start, /*!< in: recursion starting point */ trx_t* trx, /*!< in: a transaction waiting for a lock */ - lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */ + lock_t* wait_lock, /*!< in: lock that is waiting to be granted */ ulint* cost, /*!< in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return LOCK_VICTIM_IS_START */ @@ -411,7 +411,7 @@ lock_deadlock_recursive( /*********************************************************************//** Gets the nth bit of a record lock. -@return TRUE if bit set */ +@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/ UNIV_INLINE ibool lock_rec_get_nth_bit( @@ -1222,7 +1222,7 @@ lock_rec_get_first_on_page( /*********************************************************************//** Gets the next explicit lock request on a record. -@return next lock, NULL if none exists */ +@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */ UNIV_INLINE lock_t* lock_rec_get_next( @@ -3324,7 +3324,7 @@ lock_deadlock_recursive( /*====================*/ trx_t* start, /*!< in: recursion starting point */ trx_t* trx, /*!< in: a transaction waiting for a lock */ - lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */ + lock_t* wait_lock, /*!< in: lock that is waiting to be granted */ ulint* cost, /*!< in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return LOCK_VICTIM_IS_START */ @@ -3332,10 +3332,10 @@ lock_deadlock_recursive( LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we return LOCK_VICTIM_IS_START */ { + ulint ret; lock_t* lock; - ulint bit_no = ULINT_UNDEFINED; trx_t* lock_trx; - ulint ret; + ulint heap_no = ULINT_UNDEFINED; ut_a(trx); ut_a(start); @@ -3351,27 +3351,44 @@ lock_deadlock_recursive( *cost = *cost + 1; - lock = wait_lock; - if (lock_get_type_low(wait_lock) == LOCK_REC) { + ulint space; + ulint page_no; + + heap_no = lock_rec_find_set_bit(wait_lock); + ut_a(heap_no != ULINT_UNDEFINED); + + space = wait_lock->un_member.rec_lock.space; + page_no = wait_lock->un_member.rec_lock.page_no; + + lock = lock_rec_get_first_on_page_addr(space, page_no); + + /* Position the iterator on the first matching record lock. */ + while (lock != NULL + && lock != wait_lock + && !lock_rec_get_nth_bit(lock, heap_no)) { + + lock = lock_rec_get_next_on_page(lock); + } + + if (lock == wait_lock) { + lock = NULL; + } - bit_no = lock_rec_find_set_bit(wait_lock); + ut_ad(lock == NULL || lock_rec_get_nth_bit(lock, heap_no)); - ut_a(bit_no != ULINT_UNDEFINED); + } else { + lock = wait_lock; } /* Look at the locks ahead of wait_lock in the lock queue */ for (;;) { - if (lock_get_type_low(lock) & LOCK_TABLE) { - - lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, - lock); - } else { - ut_ad(lock_get_type_low(lock) == LOCK_REC); - ut_a(bit_no != ULINT_UNDEFINED); + /* Get previous table lock. */ + if (heap_no == ULINT_UNDEFINED) { - lock = (lock_t*) lock_rec_get_prev(lock, bit_no); + lock = UT_LIST_GET_PREV( + un_member.tab_lock.locks, lock); } if (lock == NULL) { @@ -3493,12 +3510,28 @@ lock_deadlock_recursive( ret = lock_deadlock_recursive( start, lock_trx, lock_trx->wait_lock, cost, depth + 1); + if (ret != 0) { return(ret); } } } + /* Get the next record lock to check. */ + if (heap_no != ULINT_UNDEFINED) { + + ut_a(lock != NULL); + + do { + lock = lock_rec_get_next_on_page(lock); + } while (lock != NULL + && lock != wait_lock + && !lock_rec_get_nth_bit(lock, heap_no)); + + if (lock == wait_lock) { + lock = NULL; + } + } }/* end of the 'for (;;)'-loop */ } diff --git a/log/log0log.c b/log/log0log.c index 063581055e918021f5e232c256373c7269ca2c0d..6ddbcd22f77f1c1d109fd0058f14471f1e488045 100644 --- a/log/log0log.c +++ b/log/log0log.c @@ -1,22 +1,5 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -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 - -*****************************************************************************/ -/***************************************************************************** - Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. Copyright (c) 2009, Google Inc. diff --git a/log/log0recv.c b/log/log0recv.c index ecbd17611eb81aaab6a801bbb291c783326662aa..d96028d9af51cf447918f9c12875d0fc95874db2 100644 --- a/log/log0recv.c +++ b/log/log0recv.c @@ -3283,6 +3283,8 @@ recv_recovery_from_checkpoint_finish(void) /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); + /* Drop temporary tables. */ + row_mysql_drop_temp_tables(); #ifdef UNIV_SYNC_DEBUG /* Wait for a while so that created threads have time to suspend diff --git a/mysql-test/innodb-autoinc-44030.result b/mysql-test/innodb-autoinc-44030.result new file mode 100644 index 0000000000000000000000000000000000000000..c0695bf0be0ecdea779475d2ee3823324ab5cc70 --- /dev/null +++ b/mysql-test/innodb-autoinc-44030.result @@ -0,0 +1,30 @@ +drop table if exists t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +d1 +1 +2 +SELECT * FROM t1; +d1 +1 +2 +INSERT INTO t1 VALUES(null); +Got one of the listed errors +ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`d1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +d1 +1 +2 +3 +DROP TABLE t1; diff --git a/mysql-test/innodb-autoinc-44030.test b/mysql-test/innodb-autoinc-44030.test new file mode 100644 index 0000000000000000000000000000000000000000..af2e3015280df8fa8847cc06926debfdddbb8461 --- /dev/null +++ b/mysql-test/innodb-autoinc-44030.test @@ -0,0 +1,34 @@ +-- source include/have_innodb.inc +# embedded server ignores 'delayed', so skip this +-- source include/not_embedded.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from +# the index (PRIMARY) +# This test requires a restart of the server +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +# Restart the server +-- source include/restart_mysqld.inc +# The MySQL and InnoDB data dictionaries should now be out of sync. +# The select should print message to the error log +SELECT * FROM t1; +# MySQL have made a change (http://lists.mysql.com/commits/75268) that no +# longer results in the two data dictionaries being out of sync. If they +# revert their changes then this check for ER_AUTOINC_READ_FAILED will need +# to be enabled. Also, see http://bugs.mysql.com/bug.php?id=47621. +-- error ER_AUTOINC_READ_FAILED,1467 +INSERT INTO t1 VALUES(null); +ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/innodb-autoinc.result b/mysql-test/innodb-autoinc.result index fe87e11c9ec5aaf9b2c2c170f348f3f82312ffba..a36b3a1a86552b04f70d95ca7a46b6234ad620af 100644 --- a/mysql-test/innodb-autoinc.result +++ b/mysql-test/innodb-autoinc.result @@ -868,35 +868,6 @@ Got one of the listed errors DROP TABLE t1; DROP TABLE t2; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; -CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (null); -INSERT INTO t1 VALUES (null); -ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; -SELECT * FROM t1; -d1 -1 -2 -SELECT * FROM t1; -d1 -1 -2 -INSERT INTO t1 VALUES(null); -Got one of the listed errors -ALTER TABLE t1 AUTO_INCREMENT = 3; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `d1` int(11) NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`d1`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 -INSERT INTO t1 VALUES(null); -SELECT * FROM t1; -d1 -1 -2 -3 -DROP TABLE t1; -SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 @@ -1190,3 +1161,86 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 DROP TABLE t1; +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (-685113344), (1), (NULL), (NULL); +SELECT * FROM t1; +c1 +-685113344 +1 +2 +3 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (-685113344), (2), (NULL), (NULL); +SELECT * FROM t1; +c1 +-685113344 +2 +3 +4 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL), (2), (-685113344), (NULL); +INSERT INTO t1 VALUES (4), (5), (6), (NULL); +SELECT * FROM t1; +c1 +-685113344 +1 +2 +3 +4 +5 +6 +7 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL), (2), (-685113344), (5); +SELECT * FROM t1; +c1 +-685113344 +1 +2 +5 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (-685113344), (NULL); +SELECT * FROM t1; +c1 +-685113344 +1 +2 +3 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/innodb-autoinc.test b/mysql-test/innodb-autoinc.test index 0630c2330a86884cb42dfdb64bfa005b95146d5f..ef0359b78b03f3009ef70282f184f2d72d169917 100644 --- a/mysql-test/innodb-autoinc.test +++ b/mysql-test/innodb-autoinc.test @@ -478,28 +478,6 @@ INSERT INTO t2 SELECT c1 FROM t1; INSERT INTO t2 SELECT NULL FROM t1; DROP TABLE t1; DROP TABLE t2; -# -# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from -# the index (PRIMARY) -# This test requires a restart of the server -SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; -CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (null); -INSERT INTO t1 VALUES (null); -ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; -SELECT * FROM t1; -# Restart the server --- source include/restart_mysqld.inc -# The MySQL and InnoDB data dictionaries should now be out of sync. -# The select should print message to the error log -SELECT * FROM t1; --- error ER_AUTOINC_READ_FAILED,1467 -INSERT INTO t1 VALUES(null); -ALTER TABLE t1 AUTO_INCREMENT = 3; -SHOW CREATE TABLE t1; -INSERT INTO t1 VALUES(null); -SELECT * FROM t1; -DROP TABLE t1; # If the user has specified negative values for an AUTOINC column then # InnoDB should ignore those values when setting the table's max value. @@ -653,3 +631,34 @@ REPLACE INTO t1 VALUES (-1); SELECT * FROM t1; SHOW CREATE TABLE t1; DROP TABLE t1; + +## +# 49497: Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (-685113344), (1), (NULL), (NULL); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (-685113344), (2), (NULL), (NULL); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL), (2), (-685113344), (NULL); +INSERT INTO t1 VALUES (4), (5), (6), (NULL); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL), (2), (-685113344), (5); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (-685113344), (NULL); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/mysql-test/innodb_bug47622.result b/mysql-test/innodb_bug47622.result new file mode 100644 index 0000000000000000000000000000000000000000..f5d13711c52a5f9fadc76dd547c83bb9805cb3a3 --- /dev/null +++ b/mysql-test/innodb_bug47622.result @@ -0,0 +1,23 @@ +CREATE TABLE bug47622( +`rule_key` int(11) NOT NULL DEFAULT '0', +`seq` smallint(6) NOT NULL DEFAULT '0', +`action` smallint(6) NOT NULL DEFAULT '0', +`arg_id` smallint(6) DEFAULT NULL, +`else_ind` TINYINT NOT NULL, +KEY IDX_A (`arg_id`) +) ENGINE=InnoDB; +ALTER TABLE bug47622 ADD UNIQUE IDX_B (rule_key,else_ind,seq,action,arg_id); +drop index IDX_B on bug47622; +create index idx on bug47622(seq, arg_id); +ALTER TABLE bug47622 ADD UNIQUE IDX_X (rule_key,else_ind,seq,action); +drop table bug47622; +CREATE TABLE bug47622 ( +`a` int(11) NOT NULL, +`b` int(11) DEFAULT NULL, +`c` char(10) DEFAULT NULL, +`d` varchar(20) DEFAULT NULL, +PRIMARY KEY (`a`), +KEY `b` (`b`) +) ENGINE=InnoDB; +alter table bug47622 add unique index (c), add index (d); +drop table bug47622; diff --git a/mysql-test/innodb_bug47622.test b/mysql-test/innodb_bug47622.test new file mode 100644 index 0000000000000000000000000000000000000000..9cf9d0e531b3b1f56ac0ddd3961186f501b633a2 --- /dev/null +++ b/mysql-test/innodb_bug47622.test @@ -0,0 +1,55 @@ +# This is the test for bug 47622. There could be index +# metadata sequence mismatch between MySQL and Innodb +# after creating index through FIC interfaces. +# We resolve the problem by sync the index sequence +# up when opening the table. + +--source include/have_innodb.inc + +connect (a,localhost,root,,); +connect (b,localhost,root,,); + +# Create a table with a non-unique index +CREATE TABLE bug47622( + `rule_key` int(11) NOT NULL DEFAULT '0', + `seq` smallint(6) NOT NULL DEFAULT '0', + `action` smallint(6) NOT NULL DEFAULT '0', + `arg_id` smallint(6) DEFAULT NULL, + `else_ind` TINYINT NOT NULL, + KEY IDX_A (`arg_id`) +) ENGINE=InnoDB; + +connection a; + +# A subsequent creating unique index should not trigger +# any error message. Unique index would be ranked ahead +# of regular index. +ALTER TABLE bug47622 ADD UNIQUE IDX_B (rule_key,else_ind,seq,action,arg_id); + +drop index IDX_B on bug47622; + +# In another connection, create additional set of normal +# index and unique index. Again, unique index would be ranked +# ahead of regular index. +connection b; +create index idx on bug47622(seq, arg_id); + +ALTER TABLE bug47622 ADD UNIQUE IDX_X (rule_key,else_ind,seq,action); + +drop table bug47622; + +# Create a table with one Primary key and a non-unique key +CREATE TABLE bug47622 ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `c` char(10) DEFAULT NULL, + `d` varchar(20) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `b` (`b`) +) ENGINE=InnoDB; + +# Add two index with one unique and one non-unique. +# Index sequence is "PRIMARY", "c", "b" and "d" +alter table bug47622 add unique index (c), add index (d); + +drop table bug47622; diff --git a/os/os0file.c b/os/os0file.c index dee52f572f22b5c388ff166f00b3f03a2889e40e..0605c0565f75f40ae5f35ba523821a8b65e68be5 100644 --- a/os/os0file.c +++ b/os/os0file.c @@ -1,20 +1,3 @@ -/***************************************************************************** - -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -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 - -*****************************************************************************/ /*********************************************************************** Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. diff --git a/row/row0ins.c b/row/row0ins.c index b881308a683412d9e40ba58465cc86c60f07474c..3259416e658f393d5a5a81a466eb88e3af26f81e 100644 --- a/row/row0ins.c +++ b/row/row0ins.c @@ -1994,7 +1994,8 @@ row_ins_index_entry_low( } btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, - search_mode, &cursor, 0, &mtr); + search_mode, + &cursor, 0, __FILE__, __LINE__, &mtr); if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) { /* The insertion was made to the insert buffer already during @@ -2053,7 +2054,8 @@ row_ins_index_entry_low( btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode | BTR_INSERT, - &cursor, 0, &mtr); + &cursor, 0, + __FILE__, __LINE__, &mtr); } } @@ -2108,7 +2110,8 @@ row_ins_index_entry_low( mtr_start(&mtr); btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, - BTR_MODIFY_TREE, &cursor, 0, &mtr); + BTR_MODIFY_TREE, &cursor, 0, + __FILE__, __LINE__, &mtr); rec = btr_cur_get_rec(&cursor); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); diff --git a/row/row0mysql.c b/row/row0mysql.c index e9fd12e97478ead20fbce92c92020ce48897d0bb..ad78c559141e500629e30f8d24279fc0c5452b3c 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -485,7 +485,7 @@ row_mysql_convert_row_to_innobase( /****************************************************************//** Handles user errors and lock waits detected by the database engine. @return TRUE if it was a lock wait and we should continue running the -query thread */ +query thread and in that case the thr is ALREADY in the running state. */ UNIV_INTERN ibool row_mysql_handle_errors( @@ -3363,6 +3363,99 @@ row_drop_table_for_mysql( return((int) err); } +/*********************************************************************//** +Drop all temporary tables during crash recovery. */ +UNIV_INTERN +void +row_mysql_drop_temp_tables(void) +/*============================*/ +{ + trx_t* trx; + ulint err; + + trx = trx_allocate_for_background(); + trx->op_info = "dropping temporary tables"; + row_mysql_lock_data_dictionary(trx); + + err = que_eval_sql( + NULL, + "PROCEDURE DROP_TEMP_TABLES_PROC () IS\n" + "table_name CHAR;\n" + "table_id CHAR;\n" + "foreign_id CHAR;\n" + "index_id CHAR;\n" + "DECLARE CURSOR c IS SELECT NAME,ID FROM SYS_TABLES\n" + "WHERE N_COLS > 2147483647\n" + /* N_COLS>>31 is set unless ROW_FORMAT=REDUNDANT, + and MIX_LEN may be garbage for those tables */ + "AND MIX_LEN=(MIX_LEN/2*2+1);\n" + /* MIX_LEN & 1 is set for temporary tables */ +#if DICT_TF2_TEMPORARY != 1 +# error "DICT_TF2_TEMPORARY != 1" +#endif + "BEGIN\n" + "OPEN c;\n" + "WHILE 1=1 LOOP\n" + " FETCH c INTO table_name, table_id;\n" + " IF (SQL % NOTFOUND) THEN\n" + " EXIT;\n" + " END IF;\n" + " WHILE 1=1 LOOP\n" + " SELECT ID INTO index_id\n" + " FROM SYS_INDEXES\n" + " WHERE TABLE_ID = table_id\n" + " LOCK IN SHARE MODE;\n" + " IF (SQL % NOTFOUND) THEN\n" + " EXIT;\n" + " END IF;\n" + + /* Do not drop tables for which there exist + foreign key constraints. */ + " SELECT ID INTO foreign_id\n" + " FROM SYS_FOREIGN\n" + " WHERE FOR_NAME = table_name\n" + " AND TO_BINARY(FOR_NAME)\n" + " = TO_BINARY(table_name)\n;" + " IF NOT (SQL % NOTFOUND) THEN\n" + " EXIT;\n" + " END IF;\n" + + " SELECT ID INTO foreign_id\n" + " FROM SYS_FOREIGN\n" + " WHERE REF_NAME = table_name\n" + " AND TO_BINARY(REF_NAME)\n" + " = TO_BINARY(table_name)\n;" + " IF NOT (SQL % NOTFOUND) THEN\n" + " EXIT;\n" + " END IF;\n" + + " DELETE FROM SYS_FIELDS\n" + " WHERE INDEX_ID = index_id;\n" + " DELETE FROM SYS_INDEXES\n" + " WHERE ID = index_id\n" + " AND TABLE_ID = table_id;\n" + " END LOOP;\n" + " DELETE FROM SYS_COLUMNS\n" + " WHERE TABLE_ID = table_id;\n" + " DELETE FROM SYS_TABLES\n" + " WHERE ID = table_id;\n" + "END LOOP;\n" + "COMMIT WORK;\n" + "END;\n" + , FALSE, trx); + + if (err != DB_SUCCESS) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Failed to drop temporary tables:" + " error %lu occurred\n", + (ulong) err); + } + + row_mysql_unlock_data_dictionary(trx); + trx_free_for_background(trx); +} + /*******************************************************************//** Drop all foreign keys in a database, see Bug#18942. Called at the end of row_drop_database_for_mysql(). @@ -3914,14 +4007,15 @@ Checks that the index contains entries in an ascending order, unique constraint is not broken, and calculates the number of index entries in the read view of the current transaction. @return TRUE if ok */ -static +UNIV_INTERN ibool -row_scan_and_check_index( -/*=====================*/ - row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in MySQL */ - dict_index_t* index, /*!< in: index */ - ulint* n_rows) /*!< out: number of entries seen in the - current consistent read */ +row_check_index_for_mysql( +/*======================*/ + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct + in MySQL handle */ + const dict_index_t* index, /*!< in: index */ + ulint* n_rows) /*!< out: number of entries + seen in the consistent read */ { dtuple_t* prev_entry = NULL; ulint matched_fields; @@ -3942,31 +4036,9 @@ row_scan_and_check_index( *n_rows = 0; - if (!row_merge_is_index_usable(prebuilt->trx, index)) { - /* A newly created index may lack some delete-marked - records that may exist in the read view of - prebuilt->trx. Thus, such indexes must not be - accessed by consistent read. */ - return(is_ok); - } - buf = mem_alloc(UNIV_PAGE_SIZE); heap = mem_heap_create(100); - /* Make a dummy template in prebuilt, which we will use - in scanning the index entries */ - - prebuilt->index = index; - /* row_merge_is_index_usable() was already checked above. */ - prebuilt->index_usable = TRUE; - prebuilt->sql_stat_start = TRUE; - prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE; - prebuilt->n_template = 0; - prebuilt->need_to_access_clustered = FALSE; - - dtuple_set_n_fields(prebuilt->search_tuple, 0); - - prebuilt->select_lock_type = LOCK_NONE; cnt = 1000; ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0); @@ -4084,119 +4156,6 @@ row_scan_and_check_index( goto loop; } -/*********************************************************************//** -Checks a table for corruption. -@return DB_ERROR or DB_SUCCESS */ -UNIV_INTERN -ulint -row_check_table_for_mysql( -/*======================*/ - row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL - handle */ -{ - dict_table_t* table = prebuilt->table; - dict_index_t* index; - ulint n_rows; - ulint n_rows_in_table = ULINT_UNDEFINED; - ulint ret = DB_SUCCESS; - ulint old_isolation_level; - - if (table->ibd_file_missing) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error:\n" - "InnoDB: MySQL is trying to use a table handle" - " but the .ibd file for\n" - "InnoDB: table %s does not exist.\n" - "InnoDB: Have you deleted the .ibd file" - " from the database directory under\n" - "InnoDB: the MySQL datadir, or have you" - " used DISCARD TABLESPACE?\n" - "InnoDB: Look from\n" - "InnoDB: " REFMAN "innodb-troubleshooting.html\n" - "InnoDB: how you can resolve the problem.\n", - table->name); - return(DB_ERROR); - } - - prebuilt->trx->op_info = "checking table"; - - old_isolation_level = prebuilt->trx->isolation_level; - - /* We must run the index record counts at an isolation level - >= READ COMMITTED, because a dirty read can see a wrong number - of records in some index; to play safe, we use always - REPEATABLE READ here */ - - prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; - - /* Enlarge the fatal lock wait timeout during CHECK TABLE. */ - mutex_enter(&kernel_mutex); - srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ - mutex_exit(&kernel_mutex); - - index = dict_table_get_first_index(table); - - while (index != NULL) { - /* fputs("Validating index ", stderr); - ut_print_name(stderr, trx, FALSE, index->name); - putc('\n', stderr); */ - - if (!btr_validate_index(index, prebuilt->trx)) { - ret = DB_ERROR; - } else { - if (!row_scan_and_check_index(prebuilt,index, &n_rows)){ - ret = DB_ERROR; - } - - if (trx_is_interrupted(prebuilt->trx)) { - ret = DB_INTERRUPTED; - break; - } - - /* fprintf(stderr, "%lu entries in index %s\n", n_rows, - index->name); */ - - if (index == dict_table_get_first_index(table)) { - n_rows_in_table = n_rows; - } else if (n_rows != n_rows_in_table) { - - ret = DB_ERROR; - - fputs("Error: ", stderr); - dict_index_name_print(stderr, - prebuilt->trx, index); - fprintf(stderr, - " contains %lu entries," - " should be %lu\n", - (ulong) n_rows, - (ulong) n_rows_in_table); - } - } - - index = dict_table_get_next_index(index); - } - - /* Restore the original isolation level */ - prebuilt->trx->isolation_level = old_isolation_level; - - /* We validate also the whole adaptive hash index for all tables - at every CHECK TABLE */ - - if (!btr_search_validate()) { - - ret = DB_ERROR; - } - - /* Restore the fatal lock wait timeout after CHECK TABLE. */ - mutex_enter(&kernel_mutex); - srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */ - mutex_exit(&kernel_mutex); - - prebuilt->trx->op_info = ""; - - return(ret); -} - /*********************************************************************//** Determines if a table is a magic monitor table. @return TRUE if monitor table */ diff --git a/srv/srv0srv.c b/srv/srv0srv.c index 3fc861a2d5d3fb37251bfb2742e2ae76b81a3b97..a3615bd4ed4c3fe6951dc3df3a4207a02dbd2487 100644 --- a/srv/srv0srv.c +++ b/srv/srv0srv.c @@ -2,6 +2,7 @@ Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. +Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -9,6 +10,13 @@ briefly in the InnoDB documentation. The contributions by Google are incorporated with their permission, and subject to the conditions contained in the file COPYING.Google. +Portions of this file contain modifications contributed and copyrighted +by Percona Inc.. Those modifications are +gratefully acknowledged and are described briefly in the InnoDB +documentation. The contributions by Percona Inc. are incorporated with +their permission, and subject to the conditions contained in the file +COPYING.Percona. + 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 Foundation; version 2 of the License. @@ -22,32 +30,6 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/*********************************************************************** - -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. -Copyright (c) 2009, Percona Inc. - -Portions of this file contain modifications contributed and copyrighted -by Percona Inc.. Those modifications are -gratefully acknowledged and are described briefly in the InnoDB -documentation. The contributions by Percona Inc. are incorporated with -their permission, and subject to the conditions contained in the file -COPYING.Percona. - -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 Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but -WITHOUT 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 - -***********************************************************************/ /**************************************************//** @file srv/srv0srv.c diff --git a/srv/srv0start.c b/srv/srv0start.c index 8fee695466e80dc58a9f75155a52a4f5c47c8da2..845850bcd9e31aba1d31784c0974bc8deb111d13 100644 --- a/srv/srv0start.c +++ b/srv/srv0start.c @@ -2,6 +2,7 @@ Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2009, Percona Inc. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -9,6 +10,13 @@ briefly in the InnoDB documentation. The contributions by Google are incorporated with their permission, and subject to the conditions contained in the file COPYING.Google. +Portions of this file contain modifications contributed and copyrighted +by Percona Inc.. Those modifications are +gratefully acknowledged and are described briefly in the InnoDB +documentation. The contributions by Percona Inc. are incorporated with +their permission, and subject to the conditions contained in the file +COPYING.Percona. + 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 Foundation; version 2 of the License. @@ -22,32 +30,6 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/*********************************************************************** - -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. -Copyright (c) 2009, Percona Inc. - -Portions of this file contain modifications contributed and copyrighted -by Percona Inc.. Those modifications are -gratefully acknowledged and are described briefly in the InnoDB -documentation. The contributions by Percona Inc. are incorporated with -their permission, and subject to the conditions contained in the file -COPYING.Percona. - -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 Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but -WITHOUT 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 - -***********************************************************************/ /********************************************************************//** @file srv/srv0start.c