diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-11-19 13:16:25 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-11-19 13:16:25 +0100 |
commit | fa3f8a18b247d5d7d86d60d016681cc188522f80 (patch) | |
tree | 180232f5e13c81e22ae9374b41be168ed9578932 /storage | |
parent | efab095c7f8f044525ce7d2313fad5f86032baab (diff) | |
parent | 543b6e02246db25d8a61574fc709b28e7720d1a0 (diff) | |
download | mariadb-git-fa3f8a18b247d5d7d86d60d016681cc188522f80.tar.gz |
mysql-5.5.34 merge
(some patches reverted, test case added)
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/btr/btr0cur.c | 18 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.c | 46 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 35 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.c | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.c | 20 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.c | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0uins.c | 15 | ||||
-rw-r--r-- | storage/innobase/row/row0umod.c | 46 | ||||
-rw-r--r-- | storage/myisam/mi_check.c | 12 |
9 files changed, 137 insertions, 61 deletions
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index b48fb705cd8..81a482e2854 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -4596,6 +4596,10 @@ next_zip_page: } } } + + DBUG_EXECUTE_IF("btr_store_big_rec_extern", + error = DB_OUT_OF_FILE_SPACE; + goto func_exit;); } func_exit: @@ -4628,9 +4632,11 @@ func_exit: field_ref = btr_rec_get_field_ref(rec, offsets, i); - /* The pointer must not be zero. */ + /* The pointer must not be zero if the operation + succeeded. */ ut_a(0 != memcmp(field_ref, field_ref_zero, - BTR_EXTERN_FIELD_REF_SIZE)); + BTR_EXTERN_FIELD_REF_SIZE) + || error != DB_SUCCESS); /* The column must not be disowned by this record. */ ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); } @@ -4726,10 +4732,10 @@ btr_free_externally_stored_field( if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) { - /* In the rollback of uncommitted transactions, we may - encounter a clustered index record whose BLOBs have - not been written. There is nothing to free then. */ - ut_a(rb_ctx == RB_RECOVERY || rb_ctx == RB_RECOVERY_PURGE_REC); + /* In the rollback, we may encounter a clustered index + record with some unwritten off-page columns. There is + nothing to free then. */ + ut_a(rb_ctx != RB_NONE); return; } diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index ab4f077bdfd..13c68169f37 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -2290,7 +2290,6 @@ loop: buf_pool, space, offset, fold); } -loop2: if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) { block = NULL; } @@ -2407,6 +2406,11 @@ wait_until_unfixed: goto loop; } + /* Buffer-fix the block so that it cannot be evicted + or relocated while we are attempting to allocate an + uncompressed page. */ + bpage->buf_fix_count++; + /* Allocate an uncompressed page. */ buf_pool_mutex_exit(buf_pool); mutex_exit(&buf_pool->zip_mutex); @@ -2416,34 +2420,20 @@ wait_until_unfixed: buf_pool_mutex_enter(buf_pool); mutex_enter(&block->mutex); + mutex_enter(&buf_pool->zip_mutex); + /* Buffer-fixing prevents the page_hash from changing. */ + ut_ad(bpage == buf_page_hash_get_low(buf_pool, + space, offset, fold)); - { - buf_page_t* hash_bpage; - - hash_bpage = buf_page_hash_get_low( - buf_pool, space, offset, fold); - - if (UNIV_UNLIKELY(bpage != hash_bpage)) { - /* The buf_pool->page_hash was modified - while buf_pool->mutex was released. - Free the block that was allocated. */ - - buf_LRU_block_free_non_file_page(block); - mutex_exit(&block->mutex); - - block = (buf_block_t*) hash_bpage; - goto loop2; - } - } - - if (UNIV_UNLIKELY - (bpage->buf_fix_count - || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) { + if (--bpage->buf_fix_count + || buf_page_get_io_fix(bpage) != BUF_IO_NONE) { - /* The block was buffer-fixed or I/O-fixed - while buf_pool->mutex was not held by this thread. - Free the block that was allocated and try again. - This should be extremely unlikely. */ + mutex_exit(&buf_pool->zip_mutex); + /* The block was buffer-fixed or I/O-fixed while + buf_pool->mutex was not held by this thread. + Free the block that was allocated and retry. + This should be extremely unlikely, for example, + if buf_page_get_zip() was invoked. */ buf_LRU_block_free_non_file_page(block); mutex_exit(&block->mutex); @@ -2454,8 +2444,6 @@ wait_until_unfixed: /* Move the compressed page from bpage to block, and uncompress it. */ - mutex_enter(&buf_pool->zip_mutex); - buf_relocate(bpage, &block->page); buf_block_init_low(block); block->lock_hash_val = lock_rec_hash(space, offset); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7a758c66b31..9c16cf73952 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -90,6 +90,9 @@ extern "C" { #include "ha_prototypes.h" #include "ut0mem.h" #include "ibuf0ibuf.h" + +enum_tx_isolation thd_get_trx_isolation(const THD* thd); + } #include "ha_innodb.h" @@ -395,6 +398,15 @@ innobase_alter_table_flags( /*=======================*/ uint flags); +/******************************************************************//** +Maps a MySQL trx isolation level code to the InnoDB isolation level code +@return InnoDB isolation level */ +static inline +ulint +innobase_map_isolation_level( +/*=========================*/ + enum_tx_isolation iso); /*!< in: MySQL isolation level code */ + static const char innobase_hton_name[]= "InnoDB"; /*************************************************************//** @@ -1196,7 +1208,8 @@ innobase_convert_from_id( } /********************************************************************** -Converts an identifier from my_charset_filename to UTF-8 charset. */ +Converts an identifier from my_charset_filename to UTF-8 charset. +@return result string length, as returned by strconvert() */ extern "C" uint innobase_convert_to_system_charset( @@ -2745,9 +2758,22 @@ innobase_start_trx_and_assign_read_view( trx_start_if_not_started(trx); - /* Assign a read view if the transaction does not have it yet */ + /* Assign a read view if the transaction does not have it yet. + Do this only if transaction is using REPEATABLE READ isolation + level. */ + trx->isolation_level = innobase_map_isolation_level( + thd_get_trx_isolation(thd)); - trx_assign_read_view(trx); + if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) { + trx_assign_read_view(trx); + } else { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_UNSUPPORTED, + "InnoDB: WITH CONSISTENT SNAPSHOT " + "was ignored because this phrase " + "can only be used with " + "REPEATABLE READ isolation level."); + } /* Set the MySQL flag to mark that there is an active transaction */ @@ -12142,7 +12168,8 @@ test_innobase_convert_name() #endif /* UNIV_COMPILE_TEST_FUNCS */ /********************************************************************** -Converts an identifier from my_charset_filename to UTF-8 charset. */ +Converts an identifier from my_charset_filename to UTF-8 charset. +@return result string length, as returned by strconvert() */ extern "C" uint innobase_convert_to_filename_charset( diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 0351951f3d2..306cdefc304 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -4373,7 +4373,6 @@ ibuf_delete_rec( BTR_MODIFY_TREE, pcur, mtr)) { mutex_exit(&ibuf_mutex); - ut_ad(!ibuf_inside(mtr)); ut_ad(mtr->state == MTR_COMMITTED); goto func_exit; } @@ -4394,7 +4393,6 @@ ibuf_delete_rec( ibuf_btr_pcur_commit_specify_mtr(pcur, mtr); func_exit: - ut_ad(!ibuf_inside(mtr)); ut_ad(mtr->state == MTR_COMMITTED); btr_pcur_close(pcur); @@ -4731,7 +4729,6 @@ loop: BTR_MODIFY_LEAF, &pcur, &mtr)) { - ut_ad(!ibuf_inside(&mtr)); ut_ad(mtr.state == MTR_COMMITTED); mops[op]++; ibuf_dummy_index_free(dummy_index); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 5c9eadeb71a..8555054b86f 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -3958,12 +3958,28 @@ row_rename_table_for_mysql( } else if (!new_is_tmp) { /* Rename all constraints. */ char new_table_name[MAX_TABLE_NAME_LEN] = ""; + char old_table_utf8[MAX_TABLE_NAME_LEN] = ""; uint errors = 0; + strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN); + innobase_convert_to_system_charset( + strchr(old_table_utf8, '/') + 1, + strchr(old_name, '/') +1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + /* Table name could not be converted from charset + my_charset_filename to UTF-8. This means that the + table name is already in UTF-8 (#mysql#50). */ + strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN); + } + info = pars_info_create(); pars_info_add_str_literal(info, "new_table_name", new_name); pars_info_add_str_literal(info, "old_table_name", old_name); + pars_info_add_str_literal(info, "old_table_name_utf8", + old_table_utf8); strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN); innobase_convert_to_system_charset( @@ -4000,6 +4016,8 @@ row_rename_table_for_mysql( "new_db_name := SUBSTR(:new_table_name, 0,\n" " new_db_name_len);\n" "old_t_name_len := LENGTH(:old_table_name);\n" + "gen_constr_prefix := CONCAT(:old_table_name_utf8,\n" + " '_ibfk_');\n" "WHILE found = 1 LOOP\n" " SELECT ID INTO foreign_id\n" " FROM SYS_FOREIGN\n" @@ -4016,7 +4034,7 @@ row_rename_table_for_mysql( " id_len := LENGTH(foreign_id);\n" " IF (INSTR(foreign_id, '/') > 0) THEN\n" " IF (INSTR(foreign_id,\n" - " '_ibfk_') > 0)\n" + " gen_constr_prefix) > 0)\n" " THEN\n" " offset := INSTR(foreign_id, '_ibfk_') - 1;\n" " new_foreign_id :=\n" diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index e4c7e37307b..518eba975ab 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -217,7 +217,8 @@ row_sel_sec_rec_is_for_clust_rec( len = clust_len; - if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL) { + if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL + && sec_len != UNIV_SQL_NULL) { if (rec_offs_nth_extern(clust_offs, clust_pos)) { len -= BTR_EXTERN_FIELD_REF_SIZE; diff --git a/storage/innobase/row/row0uins.c b/storage/innobase/row/row0uins.c index 396cc6b3390..57c8c512698 100644 --- a/storage/innobase/row/row0uins.c +++ b/storage/innobase/row/row0uins.c @@ -340,13 +340,14 @@ row_undo_ins( /* The database must have crashed after inserting a clustered index record but before writing all the externally stored columns of - that record. Because secondary index entries - are inserted after the clustered index record, - we may assume that the secondary index record - does not exist. However, this situation may - only occur during the rollback of incomplete - transactions. */ - ut_a(trx_is_recv(node->trx)); + that record, or a statement is being rolled + back because an error occurred while storing + off-page columns. + + Because secondary index entries are inserted + after the clustered index record, we may + assume that the secondary index record does + not exist. */ } else { log_free_check(); err = row_undo_ins_remove_sec(node->index, entry); diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index fae67c95c43..69831fee8ac 100644 --- a/storage/innobase/row/row0umod.c +++ b/storage/innobase/row/row0umod.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -128,11 +128,10 @@ row_undo_mod_clust_low( } /***********************************************************//** -Removes a clustered index record after undo if possible. +Purges a clustered index record after undo if possible. This is attempted when the record was inserted by updating a delete-marked record and there no longer exist transactions -that would see the delete-marked record. In other words, we -roll back the insert by purging the record. +that would see the delete-marked record. @return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */ static ulint @@ -140,11 +139,12 @@ row_undo_mod_remove_clust_low( /*==========================*/ undo_node_t* node, /*!< in: row undo node */ que_thr_t* thr, /*!< in: query thread */ - mtr_t* mtr, /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction */ ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { btr_cur_t* btr_cur; ulint err; + ulint trx_id_offset; ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); @@ -159,6 +159,42 @@ row_undo_mod_remove_clust_low( btr_cur = btr_pcur_get_btr_cur(&node->pcur); + trx_id_offset = btr_cur_get_index(btr_cur)->trx_id_offset; + + if (!trx_id_offset) { + mem_heap_t* heap = NULL; + ulint trx_id_col; + ulint* offsets; + ulint len; + + trx_id_col = dict_index_get_sys_col_pos( + btr_cur_get_index(btr_cur), DATA_TRX_ID); + ut_ad(trx_id_col > 0); + ut_ad(trx_id_col != ULINT_UNDEFINED); + + offsets = rec_get_offsets( + btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur), + NULL, trx_id_col + 1, &heap); + + trx_id_offset = rec_get_nth_field_offs( + offsets, trx_id_col, &len); + ut_ad(len == DATA_TRX_ID_LEN); + mem_heap_free(heap); + } + + if (trx_read_trx_id(btr_cur_get_rec(btr_cur) + trx_id_offset) + != node->new_trx_id) { + /* The record must have been purged and then replaced + with a different one. */ + return(DB_SUCCESS); + } + + /* We are about to remove an old, delete-marked version of the + record that may have been delete-marked by a different transaction + than the rolling-back one. */ + ut_ad(rec_get_deleted_flag(btr_cur_get_rec(btr_cur), + dict_table_is_comp(node->table))); + if (mode == BTR_MODIFY_LEAF) { err = btr_cur_optimistic_delete(btr_cur, mtr) ? DB_SUCCESS diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 7e97a751376..98a87a4e915 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2629,6 +2629,7 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, ulonglong UNINIT_VAR(key_map); pthread_attr_t thr_attr; ulong max_pack_reclength; + int error; DBUG_ENTER("mi_repair_parallel"); start_records=info->state->records; @@ -2926,12 +2927,13 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, #else param->sort_buffer_length*sort_param[i].key_length/total_key_length; #endif - if (mysql_thread_create(mi_key_thread_find_all_keys, - &sort_param[i].thr, &thr_attr, - thr_find_all_keys, - (void *) (sort_param+i))) + if ((error= mysql_thread_create(mi_key_thread_find_all_keys, + &sort_param[i].thr, &thr_attr, + thr_find_all_keys, + (void *) (sort_param+i)))) { - mi_check_print_error(param,"Cannot start a repair thread"); + mi_check_print_error(param,"Cannot start a repair thread (errno= %d)", + error); /* Cleanup: Detach from the share. Avoid others to be blocked. */ if (io_share.total_threads) remove_io_thread(&sort_param[i].read_cache); |