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: 在表 ...
随机推荐
- VBS基础篇 - 条件语句
经常地,当我们编写代码时,我们需要根据不同的判断执行不同操作,我们可以使用条件语句完成这个工作. If...Then...Else 在下面的情况中,您可以使用 If...Then...Else 语句: ...
- iOS 计算 日期 距离 当前 系统的日期 相差 多少
#pragma mark - 时间计算函数 - (NSTimeInterval)intervalSinceNow:(NSString *) theDate { NSDateFormatter * da ...
- 怎么让LinearLayout充满ScrollView
ScrollView里只能放一个元素. 当ScrollView里的元素想填满ScrollView时,使用"fill_parent"是不管用的,必需为ScrollView设置: ...
- 手写SqlHelper
SqlHelper是一个基于.NET Framework的数据库操作组件.组件中包含数据库操作方法,SqlHelper有很多版本,主要以微软一开始发布的SqlHelper类,后面包含进了Enterpr ...
- 从地址栏输入url到显示页面都发生了什么?
作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等. 本文将更深入的研究当你输入一个网址 ...
- Jquery 判断浏览器类型
$(function() { //FireFox2及以上 if ($.browser.MozillaSideBar && $.browser.version >= "1 ...
- java递归查询方法
一.需求 项目里要让用户能够设置所选择教材的章课节,以针对章课节提供相应的题目供用户做题. 设计:用户设置了教材后,首次登录,进行章节设置时.默认为用户选择第一章.第一课.第一节. 思路:用户访问页面 ...
- Bootstrap 基础
一种前端开发框架,如同YUI 下载源码找开后,其文件结构如下: bootstrap/├── css/│ ├── bootstrap.css│ ├── bootstrap.min.css│ ...
- PHP中如何给日期加上一个月 加一周 加一天
echo date("Y-m-d",strtotime("+1 month",strtotime("2012-02-04"))); 结果 ...
- LoadAssetAtPath 与 Load 的区别
一.官方的文档 Resources.LoadAssetAtPath Returns a resource at an asset path (Editor Only). This function a ...