diff options
Diffstat (limited to 'storage/xtradb/handler/ha_innodb.cc')
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 220 |
1 files changed, 186 insertions, 34 deletions
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index f7507a04412..eab16e0d4be 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -125,7 +125,6 @@ static mysql_mutex_t commit_cond_m; static mysql_mutex_t pending_checkpoint_mutex; static bool innodb_inited = 0; - #define INSIDE_HA_INNOBASE_CC /* In the Windows plugin, the return value of current_thd is @@ -207,7 +206,6 @@ static uint innobase_buffer_pool_shm_key = 0; static ulint srv_lazy_drop_table = 0; - static char* internal_innobase_data_file_path = NULL; static char* innodb_version_str = (char*) INNODB_VERSION_STR; @@ -885,6 +883,10 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_rows_read, SHOW_LONG}, {"rows_updated", (char*) &export_vars.innodb_rows_updated, SHOW_LONG}, + {"read_views_memory", + (char*) &export_vars.innodb_read_views_memory, SHOW_LONG}, + {"descriptors_memory", + (char*) &export_vars.innodb_descriptors_memory, SHOW_LONG}, {"s_lock_os_waits", (char*) &export_vars.innodb_s_lock_os_waits, SHOW_LONGLONG}, {"s_lock_spin_rounds", @@ -1311,6 +1313,8 @@ convert_error_code_to_mysql( return(HA_ERR_UNDO_REC_TOO_BIG); case DB_OUT_OF_MEMORY: return(HA_ERR_OUT_OF_MEM); + case DB_IDENTIFIER_TOO_LONG: + return(HA_ERR_INTERNAL_ERROR); } } @@ -1391,6 +1395,31 @@ innobase_convert_from_table_id( strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors); } +/********************************************************************** +Check if the length of the identifier exceeds the maximum allowed. +return true when length of identifier is too long. */ +extern "C" +my_bool +innobase_check_identifier_length( +/*=============================*/ + const char* id) /* in: FK identifier to check excluding the + database portion. */ +{ + int well_formed_error = 0; + CHARSET_INFO *cs = system_charset_info; + DBUG_ENTER("innobase_check_identifier_length"); + + uint res = cs->cset->well_formed_len(cs, id, id + strlen(id), + NAME_CHAR_LEN, + &well_formed_error); + + if (well_formed_error || res == NAME_CHAR_LEN) { + my_error(ER_TOO_LONG_IDENT, MYF(0), id); + DBUG_RETURN(true); + } + DBUG_RETURN(false); +} + /******************************************************************//** Converts an identifier to UTF-8. */ extern "C" UNIV_INTERN @@ -3098,25 +3127,29 @@ innobase_change_buffering_inited_ok: /* Force doublewrite buffer off, atomic writes replace it. */ if (srv_use_doublewrite_buf) { - fprintf(stderr, "InnoDB: Switching off doublewrite buffer " + fprintf(stderr, + "InnoDB: Switching off doublewrite buffer " "because of atomic writes.\n"); - innobase_use_doublewrite = srv_use_doublewrite_buf = FALSE; + innobase_use_doublewrite = FALSE; + srv_use_doublewrite_buf = FALSE; } - /* Force O_DIRECT on Unixes (on Windows writes are always unbuffered)*/ + /* Force O_DIRECT on Unixes (on Windows writes are always + unbuffered)*/ #ifndef _WIN32 if(!innobase_file_flush_method || - !strstr(innobase_file_flush_method, "O_DIRECT")) { - innobase_file_flush_method = + !strstr(innobase_file_flush_method, "O_DIRECT")) { + innobase_file_flush_method = srv_file_flush_method_str = (char*)"O_DIRECT"; - fprintf(stderr, "InnoDB: using O_DIRECT due to atomic writes.\n"); + fprintf(stderr, + "InnoDB: using O_DIRECT due to atomic " + "writes.\n"); } #endif #ifdef HAVE_POSIX_FALLOCATE - /* Due to a bug in directFS, using atomics needs - * posix_fallocate to extend the file - * pwrite() past end of the file won't work - */ + /* Due to a bug in directFS, using atomics needs + posix_fallocate() to extend the file, because pwrite() past the + end of the file won't work */ srv_use_posix_fallocate = TRUE; #endif } @@ -4705,7 +4738,6 @@ ha_innobase::open( dict_table_t* ib_table; char norm_name[1000]; THD* thd; - ulint retries = 0; char* is_part = NULL; ibool par_case_name_set = FALSE; char par_case_name[MAX_FULL_NAME_LEN + 1]; @@ -4745,17 +4777,13 @@ ha_innobase::open( upd_buf_size = 0; /* We look for pattern #P# to see if the table is partitioned - MySQL table. The retry logic for partitioned tables is a - workaround for http://bugs.mysql.com/bug.php?id=33349. Look - at support issue https://support.mysql.com/view.php?id=21080 - for more details. */ + MySQL table. */ #ifdef __WIN__ is_part = strstr(norm_name, "#p#"); #else is_part = strstr(norm_name, "#P#"); #endif /* __WIN__ */ -retry: /* Get pointer to a table object in InnoDB dictionary cache */ ib_table = dict_table_get(norm_name, TRUE); @@ -4772,7 +4800,7 @@ retry: share->ib_table = ib_table; if (NULL == ib_table) { - if (is_part && retries < 10) { + if (is_part) { /* MySQL partition engine hard codes the file name separator as "#P#". The text case is fixed even if lower_case_table_names is set to 1 or 2. This is true @@ -4815,11 +4843,7 @@ retry: ib_table = dict_table_get( par_case_name, FALSE); } - if (!ib_table) { - ++retries; - os_thread_sleep(100000); - goto retry; - } else { + if (ib_table) { #ifndef __WIN__ sql_print_warning("Partition table %s opened " "after converting to lower " @@ -4845,9 +4869,8 @@ retry: } if (is_part) { - sql_print_error("Failed to open table %s after " - "%lu attempts.\n", norm_name, - retries); + sql_print_error("Failed to open table %s.\n", + norm_name); } sql_print_error("Cannot find or open table %s from\n" @@ -6818,6 +6841,8 @@ ha_innobase::unlock_row(void) { DBUG_ENTER("ha_innobase::unlock_row"); + ut_ad(prebuilt->trx->state == TRX_ACTIVE); + /* Consistent read does not take any locks, thus there is nothing to unlock. */ @@ -8865,12 +8890,18 @@ innobase_rename_table( DEBUG_SYNC_C("innodb_rename_table_ready"); /* Serialize data dictionary operations with dictionary mutex: - no deadlocks can occur then in these operations */ + no deadlocks can occur then in these operations. Start the + transaction first to avoid a possible deadlock in the server. */ + trx_start_if_not_started(trx); if (lock_and_commit) { row_mysql_lock_data_dictionary(trx); } + /* Flag this transaction as a dictionary operation, so that + the data dictionary will be locked in crash recovery. */ + trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); + error = row_rename_table_for_mysql( norm_from, norm_to, trx, lock_and_commit); @@ -9423,9 +9454,11 @@ ha_innobase::info_low( prebuilt->trx->op_info = "updating table statistics"; - dict_update_statistics(ib_table, - FALSE /* update even if stats - are initialized */, called_from_analyze); + dict_update_statistics( + ib_table, + FALSE, /* update even if initialized */ + called_from_analyze, + FALSE /* update even if not changed too much */); prebuilt->trx->op_info = "returning various info to MySQL"; } @@ -12659,6 +12692,63 @@ innodb_change_buffering_update( *static_cast<const char*const*>(save); } +#ifndef DBUG_OFF +static char* srv_buffer_pool_evict; + +/****************************************************************//** +Called on SET GLOBAL innodb_buffer_pool_evict=... +Handles some values specially, to evict pages from the buffer pool. +SET GLOBAL innodb_buffer_pool_evict='uncompressed' +evicts all uncompressed page frames of compressed tablespaces. */ +static +void +innodb_buffer_pool_evict_update( +/*============================*/ + THD* thd, /*!< in: thread handle */ + struct st_mysql_sys_var*var, /*!< in: pointer to system variable */ + void* var_ptr,/*!< out: ignored */ + const void* save) /*!< in: immediate result + from check function */ +{ + if (const char* op = *static_cast<const char*const*>(save)) { + if (!strcmp(op, "uncompressed")) { + /* Evict all uncompressed pages of compressed + tables from the buffer pool. Keep the compressed + pages in the buffer pool. */ + + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool = &buf_pool_ptr[i]; + + //buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->LRU_list_mutex); + + for (buf_block_t* block = UT_LIST_GET_LAST( + buf_pool->unzip_LRU); + block != NULL; ) { + + buf_block_t* prev_block + = UT_LIST_GET_PREV(unzip_LRU, + block); + ut_ad(buf_block_get_state(block) + == BUF_BLOCK_FILE_PAGE); + ut_ad(block->in_unzip_LRU_list); + ut_ad(block->page.in_LRU_list); + + mutex_enter(&block->mutex); + buf_LRU_free_block(&block->page, + FALSE, FALSE); + mutex_exit(&block->mutex); + block = prev_block; + } + + mutex_exit(&buf_pool->LRU_list_mutex); + //buf_pool_mutex_exit(buf_pool); + } + } + } +} +#endif /* !DBUG_OFF */ + static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) { innodb_export_status(); @@ -12822,9 +12912,9 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite, static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Prevent partial page writes, via atomic writes." + "Prevent partial page writes, via atomic writes (beta). " "The option is used to prevent partial writes in case of a crash/poweroff, " - "as faster alternative to doublewrite buffer." + "as faster alternative to doublewrite buffer. " "Currently this option works only " "on Linux only with FusionIO device, and directFS filesystem.", NULL, NULL, FALSE); @@ -13046,6 +13136,13 @@ static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment, "Data file autoextend increment in megabytes", NULL, NULL, 8L, 1L, 1000L, 0); +#ifndef DBUG_OFF +static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict, + PLUGIN_VAR_RQCMDARG, + "Evict pages from the InnoDB buffer pool.", + NULL, innodb_buffer_pool_evict_update, ""); +#endif /* !DBUG_OFF */ + static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", @@ -13463,6 +13560,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(log_block_size), MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), +#ifndef DBUG_OFF + MYSQL_SYSVAR(buffer_pool_evict), +#endif /* !DBUG_OFF */ MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(buffer_pool_populate), MYSQL_SYSVAR(buffer_pool_instances), @@ -13763,6 +13863,58 @@ test_innobase_convert_name() #endif /* UNIV_COMPILE_TEST_FUNCS */ +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. */ +extern "C" +uint +innobase_convert_to_filename_charset( +/*=================================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + uint rlen; + CHARSET_INFO* cs_to = &my_charset_filename; + CHARSET_INFO* cs_from = system_charset_info; + + rlen = strconvert(cs_from, from, cs_to, to, len, &errors); + + if (errors) { + fprintf(stderr, "InnoDB: There was a problem in converting" + "'%s' in charset %s to charset %s", from, cs_from->name, + cs_to->name); + } + + return(rlen); +} + +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. */ +extern "C" +uint +innobase_convert_to_system_charset( +/*===============================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len, /* in: length of 'to', in bytes */ + uint* errors) /* out: error return */ +{ + uint rlen; + CHARSET_INFO* cs1 = &my_charset_filename; + CHARSET_INFO* cs2 = system_charset_info; + + rlen = strconvert(cs1, from, cs2, to, len, errors); + + if (*errors) { + fprintf(stderr, "InnoDB: There was a problem in converting" + "'%s' in charset %s to charset %s", from, cs1->name, + cs2->name); + } + + return(rlen); +} + /**************************************************************************** * DS-MRR implementation |