open_table
/* Open a table. SYNOPSIS open_table() thd Thread context. table_list Open first table in list. action INOUT Pointer to variable of enum_open_table_action type which will be set according to action which is required to remedy problem appeared during attempt to open table. flags Bitmap of flags to modify how open works: MYSQL_OPEN_IGNORE_FLUSH - Open table even if someone has done a flush or there is a pending exclusive metadata lock requests against it (i.e. request high priority metadata lock). No version number checking is done. MYSQL_OPEN_TEMPORARY_ONLY - Open only temporary table not the base table or view. MYSQL_OPEN_TAKE_UPGRADABLE_MDL - Obtain upgradable metadata lock for tables on which we are going to take some kind of write table-level lock. IMPLEMENTATION Uses a cache of open tables to find a table not in use. If TABLE_LIST::open_strategy is set to OPEN_IF_EXISTS, the table is opened only if it exists. If the open strategy is OPEN_STUB, the underlying table is never opened. In both cases, metadata locks are always taken according to the lock strategy. RETURN TRUE Open failed. "action" parameter may contain type of action needed to remedy problem before retrying again. FALSE Success. Members of TABLE_LIST structure are filled properly (e.g. TABLE_LIST::table is set for real tables and TABLE_LIST::view is set for views). */ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, Open_table_context *ot_ctx) { reg1 TABLE *table; char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; uint flags= ot_ctx->get_flags(); MDL_ticket *mdl_ticket; int error; TABLE_SHARE *share; my_hash_value_type hash_value; DBUG_ENTER("open_table"); /* an open table operation needs a lot of the stack space */ if (check_stack_overrun(thd, STACK_MIN_SIZE_FOR_OPEN, (uchar *)&alias)) DBUG_RETURN(TRUE); if (thd->killed) DBUG_RETURN(TRUE); key_length= (create_table_def_key(thd, key, table_list, ) - TMP_TABLE_KEY_EXTRA); /* Unless requested otherwise, try to resolve this table in the list of temporary tables of this thread. In MySQL temporary tables are always thread-local and "shadow" possible base tables with the same name. This block implements the behaviour. TODO: move this block into a separate function. */ if (table_list->open_type != OT_BASE_ONLY && ! (flags & MYSQL_OPEN_SKIP_TEMPORARY)) { for (table= thd->temporary_tables; table ; table=table->next) { if (table->s->table_cache_key.length == key_length + TMP_TABLE_KEY_EXTRA && !memcmp(table->s->table_cache_key.str, key, key_length + TMP_TABLE_KEY_EXTRA)) { /* We're trying to use the same temporary table twice in a query. Right now we don't support this because a temporary table is always represented by only one TABLE object in THD, and it can not be cloned. Emit an error for an unsupported behaviour. */ if (table->query_id) { DBUG_PRINT("error", ("query_id: %lu server_id: %u pseudo_thread_id: %lu", (ulong) table->query_id, (uint) thd->server_id, (ulong) thd->variables.pseudo_thread_id)); my_error(ER_CANT_REOPEN_TABLE, MYF(), table->alias); DBUG_RETURN(TRUE); } table->query_id= thd->query_id; thd->thread_specific_used= TRUE; DBUG_PRINT("info",("Using temporary table")); goto reset; } } } if (table_list->open_type == OT_TEMPORARY_ONLY || (flags & MYSQL_OPEN_TEMPORARY_ONLY)) { if (table_list->open_strategy == TABLE_LIST::OPEN_NORMAL) { my_error(ER_NO_SUCH_TABLE, MYF(), table_list->db, table_list->table_name); DBUG_RETURN(TRUE); } else DBUG_RETURN(FALSE); } /* The table is not temporary - if we're in pre-locked or LOCK TABLES mode, let's try to find the requested table in the list of pre-opened and locked tables. If the table is not there, return an error - we can't open not pre-opened tables in pre-locked/LOCK TABLES mode. TODO: move this block into a separate function. */ if (thd->locked_tables_mode && ! (flags & MYSQL_OPEN_GET_NEW_TABLE)) { // Using table locks TABLE *best_table= ; int best_distance= INT_MIN; for (table=thd->open_tables; table ; table=table->next) { if (table->s->table_cache_key.length == key_length && !memcmp(table->s->table_cache_key.str, key, key_length)) { if (!my_strcasecmp(system_charset_info, table->alias, alias) && table->query_id != thd->query_id && /* skip tables already used */ (thd->locked_tables_mode == LTM_LOCK_TABLES || table->query_id == )) { int distance= ((int) table->reginfo.lock_type - (int) table_list->lock_type); /* Find a table that either has the exact lock type requested, or has the best suitable lock. In case there is no locked table that has an equal or higher lock than requested, we us the closest matching lock to be able to produce an error message about wrong lock mode on the table. The best_table is changed if bd < 0 <= d or bd < d < 0 or 0 <= d < bd. distance < 0 - No suitable lock found distance > 0 - we have lock mode higher then we require distance == 0 - we have lock mode exactly which we need */ && distance > best_distance) || (distance >= && distance < best_distance)) { best_distance= distance; best_table= table; ) { /* We have found a perfect match and can finish iterating through open tables list. Check for table use conflict between calling statement and SP/trigger is done in lock_tables(). */ break; } } } } } if (best_table) { table= best_table; table->query_id= thd->query_id; DBUG_PRINT("info",("Using locked table")); goto reset; } /* Is this table a view and not a base table? (it is work around to allow to open view with locked tables, real fix will be made after definition cache will be made) Since opening of view which was not explicitly locked by LOCK TABLES breaks metadata locking protocol (potentially can lead to deadlocks) it should be disallowed. */ if (thd->mdl_context.is_lock_owner(MDL_key::TABLE, table_list->db, table_list->table_name, MDL_SHARED)) { ]; enum legacy_db_type not_used; build_table_filename(path, , table_list->db, table_list->table_name, reg_ext, ); /* Note that we can't be 100% sure that it is a view since it's possible that we either simply have not found unused TABLE instance in THD::open_tables list or were unable to open table during prelocking process (in this case in theory we still should hold shared metadata lock on it). */ if (dd_frm_type(thd, path, ¬_used) == FRMTYPE_VIEW) { if (!tdc_open_view(thd, table_list, alias, key, key_length, mem_root, )) { DBUG_ASSERT(table_list->view != ); DBUG_RETURN(FALSE); // VIEW } } } /* No table in the locked tables list. In case of explicit LOCK TABLES this can happen if a user did not include the able into the list. In case of pre-locked mode locked tables list is generated automatically, so we may only end up here if the table did not exist when locked tables list was created. */ if (thd->locked_tables_mode == LTM_PRELOCKED) my_error(ER_NO_SUCH_TABLE, MYF(), table_list->db, table_list->alias); else my_error(ER_TABLE_NOT_LOCKED, MYF(), alias); DBUG_RETURN(TRUE); } /* Non pre-locked/LOCK TABLES mode, and the table is not temporary. This is the normal use case. */ if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK)) { /* We are not under LOCK TABLES and going to acquire write-lock/ modify the base table. We need to acquire protection against global read lock until end of this statement in order to have this statement blocked by active FLUSH TABLES WITH READ LOCK. We don't block acquire this protection under LOCK TABLES as such protection already acquired at LOCK TABLES time and not released until UNLOCK TABLES. We don't block statements which modify only temporary tables as these tables are not preserved by backup by any form of backup which uses FLUSH TABLES WITH READ LOCK. TODO: The fact that we sometimes acquire protection against GRL only when we encounter table to be write-locked slightly increases probability of deadlock. This problem will be solved once Alik pushes his temporary table refactoring patch and we can start pre-acquiring metadata locks at the beggining of open_tables() call. */ if (table_list->mdl_request.type >= MDL_SHARED_WRITE && ! (flags & (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | MYSQL_OPEN_FORCE_SHARED_MDL | MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)) && ! ot_ctx->has_protection_against_grl()) { MDL_request protection_request; MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); if (thd->global_read_lock.can_acquire_protection()) DBUG_RETURN(TRUE); protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT); /* Install error handler which if possible will convert deadlock error into request to back-off and restart process of opening tables. */ thd->push_internal_handler(&mdl_deadlock_handler); bool result= thd->mdl_context.acquire_lock(&protection_request, ot_ctx->get_timeout()); thd->pop_internal_handler(); if (result) DBUG_RETURN(TRUE); ot_ctx->set_has_protection_against_grl(); } if (open_table_get_mdl_lock(thd, ot_ctx, &table_list->mdl_request, flags, &mdl_ticket) || mdl_ticket == NULL) { DEBUG_SYNC(thd, "before_open_table_wait_refresh"); DBUG_RETURN(TRUE); } DEBUG_SYNC(thd, "after_open_table_mdl_shared"); } else { /* Grab reference to the MDL lock ticket that was acquired by the caller. */ mdl_ticket= table_list->mdl_request.ticket; } hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); if (table_list->open_strategy == TABLE_LIST::OPEN_IF_EXISTS) { bool exists; if (check_if_table_exists(thd, table_list, &exists)) DBUG_RETURN(TRUE); if (!exists) DBUG_RETURN(FALSE); /* Table exists. Let us try to open it. */ } else if (table_list->open_strategy == TABLE_LIST::OPEN_STUB) DBUG_RETURN(FALSE); retry_share: mysql_mutex_lock(&LOCK_open); /** *如果从table_def_cache中找不到合适的table_share,就要生成一个新的table_share *打开.frm文件,填充数据,并放到table_def_cache哈希中 *同时share的引用值加1 即table_share->ref_count++ *如果table_def_cache中元素个数超过400,从oldest_unused_share开始,定位其table_share在table_def_cache中的位置,并删除 *因为是新生成的table_share,所以它的free_tables肯定为空,所以就要table_share的实例化 *实例化:例如将table_share赋值给table的成员变量s *调用table_share的成员对象used_table的方法push_front(),将table添加进去 * *如果table_share->free_tables为空, *如果table的实例超过400,说明要根据LRU,在unused_tables全局链表中,删除一些table实例 *unused_tables的头结点是最近最久未使用的,尾结点是最新的 *取出头结点 判断table->in_used的值 *如果不为0,说明还在使用 执行table->s->used_tables.remove(table) *如果为0,说明不再使用,执行table->s->free_tales.remove(table),并且删除该头结点 *table->s->ref_count--,如果值为0,将table_share放到end_unused_table_share的前面,符合LRU规则块 * *之所以这里不删除table_def_cache中数据,估计是认为这块只是删除unused_tables中的数据 */ /** *不会主动close_table的,除非用户手动执行alter或flush tales *当close_table(table)时 *设置table->in_used为0, *调用table->s->used_tables.remove(table) *table->s->free_tables.push_front(table) *并将该table作为unused_tables全局链表的头结点 */ if (!(share= get_table_share_with_discover(thd, table_list, key, key_length, OPEN_VIEW, &error, hash_value))) { DBUG_RETURN(TRUE); } if (!share->free_tables.is_empty()) { table= share->free_tables.front(); table_def_use_table(thd, table); /* We need to release share as we have EXTRA reference to it in our hands. */ release_table_share(share); } else { /* We have too many TABLE instances around let us try to get rid of them. */ while (table_cache_count > table_cache_size && unused_tables) free_cache_entry(unused_tables); mysql_mutex_unlock(&LOCK_open); /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) goto err_lock; error= open_table_from_share(thd, share, alias, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), (READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD), thd->open_options, table, FALSE); if (open_table_entry_fini(thd, share, table)) { closefrm(table, ); my_free(table); goto err_lock; } mysql_mutex_lock(&LOCK_open); /* Add table to the share's used tables list. */ table_def_add_used_table(thd, table); } mysql_mutex_unlock(&LOCK_open); table->mdl_ticket= mdl_ticket; table->next= thd->open_tables; /* Link into simple list */ thd->set_open_tables(table); table->reginfo.lock_type=TL_READ; /* Assume read */ reset: /* Check that there is no reference to a condtion from an earlier query (cf. Bug#58553). */ DBUG_ASSERT(table->file->pushed_cond == NULL); table_list->updatable= ; // It is not derived table nor non-updatable VIEW table_list->table= table; table->init(thd, table_list); DBUG_RETURN(FALSE); err_lock: mysql_mutex_lock(&LOCK_open); err_unlock: release_table_share(share); mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(TRUE); }
/* Open a table based on a TABLE_SHARE SYNOPSIS open_table_from_share() thd Thread handler share Table definition alias Alias for table db_stat open flags (for example HA_OPEN_KEYFILE| HA_OPEN_RNDFILE..) can be 0 (example in ha_example_table) prgflag READ_ALL etc.. ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc.. outparam result table RETURN VALUES 0 ok 1 Error (see open_table_error) 2 Error (see open_table_error) 3 Wrong data in .frm file 4 Error (see open_table_error) 5 Error (see open_table_error: charset unavailable) 7 Table definition has changed in engine */ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, bool is_create_table) { int error; uint records, i, bitmap_size; bool error_reported= FALSE; uchar *record, *bitmaps; Field **field_ptr; DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, share->table_name.str, (long) outparam)); error= ; bzero((char*) outparam, sizeof(*outparam)); outparam->in_use= thd; outparam->s= share; outparam->db_stat= db_stat; outparam->write_row_record= NULL; init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, ); if (!(outparam->alias= my_strdup(alias, MYF(MY_WME)))) goto err; outparam->quick_keys.init(); outparam->covering_keys.init(); outparam->merge_keys.init(); outparam->keys_in_use_for_query.init(); /* Allocate handler */ outparam->file= ; if (!(prgflag & OPEN_FRM_FILE_ONLY)) { /** *详见 *生成句柄,类型为handler */ if (!(outparam->file= get_new_handler(share, &outparam->mem_root, share->db_type()))) goto err; } else { DBUG_ASSERT(!db_stat); } error= ; outparam->reginfo.lock_type= TL_UNLOCK; outparam->current_lock= F_UNLCK; records=; if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN)) records=; if (prgflag & (READ_ALL+EXTRA_RECORD)) records++; if (!(record= (uchar*) alloc_root(&outparam->mem_root, share->rec_buff_length * records))) goto err; /* purecov: inspected */ ) { /* We are probably in hard repair, and the buffers should not be used */ outparam->record[]= outparam->record[]= share->default_values; } else { outparam->record[]= record; ) outparam->record[]= record+ share->rec_buff_length; else outparam->record[]= outparam->record[]; // Safety } #ifdef HAVE_purify /* We need this because when we read var-length rows, we are not updating bytes after end of varchar */ ) { memcpy(outparam->record[], share->default_values, share->rec_buff_length); memcpy(outparam->record[], share->default_values, share->null_bytes); ) memcpy(outparam->record[], share->default_values, share->rec_buff_length); } #endif if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, ()* sizeof(Field*))))) goto err; /* purecov: inspected */ outparam->field= field_ptr; record= (uchar*) outparam->record[]-; /* Fieldstart = 1 */ if (share->null_field_first) outparam->null_flags= (uchar*) record+; else outparam->null_flags= (uchar*) (record+ + share->reclength - share->null_bytes); /* Setup copy of fields from share, but use the right alias and record */ ; i < share->fields; i++, field_ptr++) { if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam))) goto err; } (*field_ptr)= ; // End marker if (share->found_next_number_field) outparam->found_next_number_field= outparam->field[(uint) (share->found_next_number_field - share->field)]; if (share->timestamp_field) outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset]; /* Fix key->name and key_part->field */ if (share->key_parts) { KEY *key_info, *key_info_end; KEY_PART_INFO *key_part; uint n_length; n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO); if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length))) goto err; outparam->key_info= key_info; key_part= (reinterpret_cast<KEY_PART_INFO*>(key_info+share->keys)); memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys); memcpy(key_part, share->key_info[].key_part, (sizeof(*key_part) * share->key_parts)); for (key_info_end= key_info + share->keys ; key_info < key_info_end ; key_info++) { KEY_PART_INFO *key_part_end; key_info->table= outparam; key_info->key_part= key_part; for (key_part_end= key_part+ key_info->key_parts ; key_part < key_part_end ; key_part++) { Field *field= key_part->field= outparam->field[key_part->fieldnr-]; if (field->key_length() != key_part->length && !(field->flags & BLOB_FLAG)) { /* We are using only a prefix of the column as a key: Create a new field for the key part that matches the index */ field= key_part->field=field->new_field(&outparam->mem_root, outparam, ); field->field_length= key_part->length; } } } } #ifdef WITH_PARTITION_STORAGE_ENGINE if (share->partition_info_str_len && outparam->file) { /* In this execution we must avoid calling thd->change_item_tree since we might release memory before statement is completed. We do this by changing to a new statement arena. As part of this arena we also set the memory root to be the memory root of the table since we call the parser and fix_fields which both can allocate memory for item objects. We keep the arena to ensure that we can release the free_list when closing the table object. SEE Bug #21658 */ Query_arena *backup_stmt_arena_ptr= thd->stmt_arena; Query_arena backup_arena; Query_arena part_func_arena(&outparam->mem_root, Query_arena::STMT_INITIALIZED); thd->set_n_backup_active_arena(&part_func_arena, &backup_arena); thd->stmt_arena= &part_func_arena; bool tmp; bool work_part_info_used; tmp= mysql_unpack_partition(thd, share->partition_info_str, share->partition_info_str_len, outparam, is_create_table, share->default_part_db_type, &work_part_info_used); if (tmp) { thd->stmt_arena= backup_stmt_arena_ptr; thd->restore_active_arena(&part_func_arena, &backup_arena); goto partititon_err; } outparam->part_info->is_auto_partitioned= share->auto_partitioned; DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); /* we should perform the fix_partition_func in either local or caller's arena depending on work_part_info_used value */ if (!work_part_info_used) tmp= fix_partition_func(thd, outparam, is_create_table); thd->stmt_arena= backup_stmt_arena_ptr; thd->restore_active_arena(&part_func_arena, &backup_arena); if (!tmp) { if (work_part_info_used) tmp= fix_partition_func(thd, outparam, is_create_table); } outparam->part_info->item_free_list= part_func_arena.free_list; partititon_err: if (tmp) { if (is_create_table) { /* During CREATE/ALTER TABLE it is ok to receive errors here. It is not ok if it happens during the opening of an frm file as part of a normal query. */ error_reported= TRUE; } goto err; } } #endif /* Allocate bitmaps */ bitmap_size= share->column_bitmap_size; ))) goto err; bitmap_init(&outparam->def_read_set, (my_bitmap_map*) bitmaps, share->fields, FALSE); bitmap_init(&outparam->def_write_set, (my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE); bitmap_init(&outparam->tmp_set, (my_bitmap_map*) (bitmaps+bitmap_size*), share->fields, FALSE); outparam->default_column_bitmaps(); /* The table struct is now initialized; Open the table */ error= ; if (db_stat) { int ha_err; /** *详见 *打开.ibd文件,初始化dict_table_t */ if ((ha_err= (outparam->file-> ha_open(outparam, share->normalized_path.str, (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : ((db_stat & HA_WAIT_IF_LOCKED) || (specialflag & SPECIAL_WAIT_IF_LOCKED)) ? HA_OPEN_WAIT_IF_LOCKED : (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? HA_OPEN_ABORT_IF_LOCKED : HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags)))) { /* Set a flag if the table is crashed and it can be auto. repaired */ share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) && outparam->file->auto_repair() && !(ha_open_flags & HA_OPEN_FOR_REPAIR)); switch (ha_err) { case HA_ERR_NO_SUCH_TABLE: /* The table did not exists in storage engine, use same error message as if the .frm file didn't exist */ error= ; my_errno= ENOENT; break; case EMFILE: /* Too many files opened, use same error message as if the .frm file can't open */ DBUG_PRINT("error", ("open file: %s failed, too many files opened (errno: %d)", share->normalized_path.str, ha_err)); error= ; my_errno= EMFILE; break; default: outparam->file->print_error(ha_err, MYF()); error_reported= TRUE; if (ha_err == HA_ERR_TABLE_DEF_CHANGED) error= ; break; } goto err; /* purecov: inspected */ } } #if defined(HAVE_purify) && !defined(DBUG_OFF) bzero((); #endif outparam->no_replicate= outparam->file && test(outparam->file->ha_table_flags() & HA_HAS_OWN_BINLOGGING); /* Increment the opened_tables counter, only when open flags set. */ if (db_stat) thd->status_var.opened_tables++; DBUG_RETURN (); err: if (! error_reported) open_table_error(share, error, my_errno, ); delete outparam->file; #ifdef WITH_PARTITION_STORAGE_ENGINE if (outparam->part_info) free_items(outparam->part_info->item_free_list); #endif outparam->file= ; // For easier error checking outparam->db_stat=; free_root(&outparam->mem_root, MYF()); // Safe to call on bzero'd root my_free((void *) outparam->alias); DBUG_RETURN (error); }
/** Mark already existing TABLE instance as used. */ static void table_def_use_table(THD *thd, TABLE *table) { DBUG_ASSERT(!table->in_use); /* Unlink table from list of unused tables for this share. */ table->s->free_tables.remove(table); /* Unlink able from global unused tables list. */ if (table == unused_tables) { // First unused unused_tables=unused_tables->next; // Remove from link if (table == unused_tables) unused_tables=; } table->prev->next=table->next; /* Remove from unused list */ table->next->prev=table->prev; check_unused(); /* Add table to list of used tables for this share. */ table->s->used_tables.push_front(table); table->in_use= thd; /* The ex-unused table must be fully functional. */ DBUG_ASSERT(table->db_stat && table->file); /* The children must be detached from the table. */ DBUG_ASSERT(! table->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN)); }
static void table_def_add_used_table(THD *thd, TABLE *table) { DBUG_ASSERT(table->in_use == thd); table->s->used_tables.push_front(table); table_cache_count++; }
int handler::ha_open(TABLE *table_arg, const char *name, int mode, int test_if_locked) { int error; DBUG_ENTER("handler::ha_open"); DBUG_PRINT("enter", ("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d", name, ht->db_type, table_arg->db_stat, mode, test_if_locked)); table= table_arg; DBUG_ASSERT(table->s == table_share); DBUG_ASSERT(alloc_root_inited(&table->mem_root)); if ((error=open(name,mode,test_if_locked))) { if ((error == EACCES || error == EROFS) && mode == O_RDWR && (table->db_stat & HA_TRY_READ_ONLY)) { table->db_stat|=HA_READ_ONLY; error=open(name,O_RDONLY,test_if_locked); } } if (error) { my_errno= error; /* Safeguard */ DBUG_PRINT("error",("error: %d errno: %d",error,errno)); } else { if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA) table->db_stat|=HA_READ_ONLY; (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL /* ref is already allocated for us if we're called from handler::clone() */ if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*))) { close(); error=HA_ERR_OUT_OF_MEM; } else dup_ref=ref+ALIGN_SIZE(ref_length); cached_table_flags= table_flags(); } DBUG_RETURN(error); }
open_table的更多相关文章
- open_table与opened_table
好多人在调优Mysql的时候,总是对open_tables和opend_tables两个参数分别不清. 网上好多解释都是这样的:open_tables:当前打开表的数量opened_tables:当前 ...
- open_table与opened_table --2
好多人在调优Mysql的时候,总是对open_tables和opend_tables两个参数分别不清. 网上好多解释都是这样的:open_tables:当前打开表的数量opened_tables:当前 ...
- MySQL备份锁
无论逻辑备份还是物理备份,为了获取一致性位点,都强依赖于FTWRL(Flush Table With Read Lock).这个锁杀伤力非常大,因为持有锁的这段时间,整个数据库实质上不能对外提供写服务 ...
- rabbitmq启动异常之error,{not_a_dets_file recovery.dets
中午,公司群里面测试人员@笔者说,早上测试服务器异常,MQ起不来,重启os了也起不来,报错,上去看下了早上又因为内存oom被内核killed了,启动了下,确实启动报错,erl vm进程起来了,但是be ...
- Mysql查询阻塞初探
第一次值班,报警打电话给我说,数据库复制延时一个多小时,那个时候是半夜啊,但我还是很清醒的起来,开机.vpn.登录.show processlist,结果发现情况是这样的: 红线框表示的是当前每个线程 ...
- 【网络资料】Astar算法详解
关于A*算法,很早就想写点什么,可是貌似天天在忙活着什么,可事实又没有做什么,真是浮躁啊!所以今晚还是来写一下总结吧! A*算法是很经典的只能启发式搜索算法,关于只能搜索算法和一般的搜索算法(例如DF ...
- struct TABLE
struct TABLE { TABLE() {} /* Remove gcc warning */ TABLE_SHARE *s; handler *file; TABLE *next, *prev ...
- MySQL锁系列3 MDL锁
http://www.cnblogs.com/xpchild/p/3790139.html MySQL为了保护数据字典元数据,使用了metadata lock,即MDL锁,保证在并发的情况下,结构 ...
- MySQL锁系列2 表锁
http://www.cnblogs.com/xpchild/p/3789068.html 上一篇介绍了MySQL源码中保护内存结构或变量的锁,这里开始介绍下MySQL事务中的表锁. 注1: 在表 ...
随机推荐
- 常见的装置与其在Linux当中的档名
需要特别留意的是硬盘机(不论是IDE/SCSI/U盘都一样),每个磁碟机的磁盘分区(partition)不同时, 其磁碟档名还会改变呢!下一小节我们会介绍磁盘分区的相关概念啦!需要特别注意的是磁带机的 ...
- android 讯飞语音识别(离线)注意事项
讯飞语音识别:使用注意事项:mainfest.xml中一定要记得权限写进去21001:我的情况是没有写SpeechApp类,并且需要在application中注册:20005:无匹配结果23300:本 ...
- ora-28002 the password will expire解决办法
Oracle11g R2数据库提示ORA-28002: the password will expire within 5 days,是说密码过期,将Oracle密码设置成永不过期就可以了,不过并不推 ...
- 2013 Asia Hangzhou Regional Contest
Lights Against Dudely http://acm.hdu.edu.cn/showproblem.php?pid=4770 15个位置,所以可以暴力枚举那些放,对于放的再暴力枚举哪个转, ...
- Tower of Hanoi问题
[问题描述] 有A, B, C三个塔座,A上套有n个直径不同的圆 盘,按直径从小到大叠放,形如宝塔,编号1, 2, 3 … n. 要求将n个圆盘从A移到C,叠放顺序不变,移动过程中遵循 下列原则: w ...
- Scrum敏捷开发简介
Agile 敏捷开发实践中,强调团队的自我管理.在 Scrum 中,自我团队管理体现在每天的 Scrum 会议中和日常的协同工作,在每天的 Scrum 例会中,团队成员一般回答一下几个问题 : 昨天完 ...
- java基础知识回顾之javaIO类--File类应用:递归深度遍历文件
代码如下: package com.lp.ecjtu.File.FileDeepList; import java.io.File; public class FileDeepList { /** * ...
- C Primer Plus 第4章 字符串和格式化输入/输出 编程练习
1. #include <stdio.h> int main(void) { ]; ]; printf("请输入您的名字: "); scanf("%s&quo ...
- lintcode:数飞机
数飞机 给出飞机的起飞和降落时间的列表,用 interval 序列表示. 请计算出天上同时最多有多少架飞机? 如果多架飞机降落和起飞在同一时刻,我们认为降落有优先权. 样例 对于每架飞机的起降时间列表 ...
- POSIX semaphore: sem_open, sem_close, sem_post, sem_wait
http://www.cnblogs.com/BloodAndBone/archive/2011/01/18/1938552.html 一.Posix有名信号灯 1.posix有名信号灯函数 函数se ...