zoukankan      html  css  js  c++  java
  • ha_innobase::open

     http://mysql.taobao.org/monthly/2015/08/07/

    /*****************************************************************//**
    Creates and opens a handle to a table which already exists in an InnoDB
    database.
    @return    1 if error, 0 if success */
    UNIV_INTERN
    int
    ha_innobase::open(
    /*==============*/
        const char*        name,        /*!< in: table name */
        int            mode,        /*!< in: not used */
        uint            test_if_locked)    /*!< in: not used */
    {
        dict_table_t*        ib_table;
        char            norm_name[1000];
        THD*            thd;
        char*            is_part = NULL;
        ibool            par_case_name_set = FALSE;
        char            par_case_name[MAX_FULL_NAME_LEN + 1];
        dict_err_ignore_t    ignore_err = DICT_ERR_IGNORE_NONE;
    
        DBUG_ENTER("ha_innobase::open");
    
        thd = ha_thd();
    
        normalize_table_name(norm_name, name);
    
        user_thd = NULL;
    
        if (!(share=get_share(name))) {
    
            DBUG_RETURN(1);
        }
    
        /* Will be allocated if it is needed in ::update_row() */
        upd_buf = NULL;
        upd_buf_size = 0;
    
       /* Get pointer to a table object in InnoDB dictionary cache */
        ib_table = dict_table_get(norm_name, TRUE, ignore_err);
    
    table_opened:
    
       
        prebuilt = row_create_prebuilt(ib_table, table->s->reclength);
    
        prebuilt->default_rec = table->s->default_values;
        ut_ad(prebuilt->default_rec);
    
        /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
    
        primary_key = table->s->primary_key;
        key_used_on_scan = primary_key;
    
       /* 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
        references for equality by doing a simple memcmp on the strings
        of length ref_length! */
    
        if (!row_table_got_default_clust_index(ib_table)) {
    
            prebuilt->clust_index_was_generated = FALSE;
    
            if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
                sql_print_error("Table %s has a primary key in "
                        "InnoDB data dictionary, but not "
                        "in MySQL!", name);
    
                /* This mismatch could cause further problems
                if not attended, bring this to the user's attention
                by printing a warning in addition to log a message
                in the errorlog */
                push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                            ER_NO_SUCH_INDEX,
                            "InnoDB: Table %s has a "
                            "primary key in InnoDB data "
                            "dictionary, but not in "
                            "MySQL!", name);
    
                /* If primary_key >= MAX_KEY, its (primary_key)
                value could be out of bound if continue to index
                into key_info[] array. Find InnoDB primary index,
                and assign its key_length to ref_length.
                In addition, since MySQL indexes are sorted starting
                with primary index, unique index etc., initialize
                ref_length to the first index key length in
                case we fail to find InnoDB cluster index.
    
                Please note, this will not resolve the primary
                index mismatch problem, other side effects are
                possible if users continue to use the table.
                However, we allow this table to be opened so
                that user can adopt necessary measures for the
                mismatch while still being accessible to the table
                date. */
                ref_length = table->key_info[0].key_length;
    
                /* Find correspoinding cluster index
                key length in MySQL's key_info[] array */
                for (ulint i = 0; i < table->s->keys; i++) {
                    dict_index_t*    index;
                    index = innobase_get_index(i);
                    if (dict_index_is_clust(index)) {
                        ref_length =
                             table->key_info[i].key_length;
                    }
                }
            } else {
                /* MySQL allocates the buffer for ref.
                key_info->key_length includes space for all key
                columns + one byte for each column that may be
                NULL. ref_length must be as exact as possible to
                save space, because all row reference buffers are
                allocated based on ref_length. */
    
                ref_length = table->key_info[primary_key].key_length;
            }
        } else {
            if (primary_key != MAX_KEY) {
                sql_print_error(
                    "Table %s has no primary key in InnoDB data "
                    "dictionary, but has one in MySQL! If you "
                    "created the table with a MySQL version < "
                    "3.23.54 and did not define a primary key, "
                    "but defined a unique key with all non-NULL "
                    "columns, then MySQL internally treats that "
                    "key as the primary key. You can fix this "
                    "error by dump + DROP + CREATE + reimport "
                    "of the table.", name);
    
                /* This mismatch could cause further problems
                if not attended, bring this to the user attention
                by printing a warning in addition to log a message
                in the errorlog */
                push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                            ER_NO_SUCH_INDEX,
                            "InnoDB: Table %s has no "
                            "primary key in InnoDB data "
                            "dictionary, but has one in "
                            "MySQL!", name);
            }
    
            prebuilt->clust_index_was_generated = TRUE;
    
            ref_length = DATA_ROW_ID_LEN;
    
            /* If we automatically created the clustered index, then
            MySQL does not know about it, and MySQL must NOT be aware
            of the index used on scan, to make it avoid checking if we
            update the column of the index. That is why we assert below
            that key_used_on_scan is the undefined value MAX_KEY.
            The column is the row id in the automatical generation case,
            and it will never be updated anyway. */
    
            if (key_used_on_scan != MAX_KEY) {
                sql_print_warning(
                    "Table %s key_used_on_scan is %lu even "
                    "though there is no primary key inside "
                    "InnoDB.", name, (ulong) key_used_on_scan);
            }
        }
    
        /* Index block size in InnoDB: used by MySQL in query optimization */
        stats.block_size = 16 * 1024;
    
        /* Init table lock structure */
        thr_lock_data_init(&share->lock,&lock,(void*) 0);
    
        if (prebuilt->table) {
            /* We update the highest file format in the system table
            space, if this table has higher file format setting. */
    
            trx_sys_file_format_max_upgrade(
                (const char**) &innobase_file_format_max,
                dict_table_get_format(prebuilt->table));
        }
    
        /* Only if the table has an AUTOINC column. */
        if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
            dict_table_autoinc_lock(prebuilt->table);
    
            /* Since a table can already be "open" in InnoDB's internal
            data dictionary, we only init the autoinc counter once, the
            first time the table is loaded. We can safely reuse the
            autoinc value from a previous MySQL open. */
            if (dict_table_autoinc_read(prebuilt->table) == 0) {
    
                innobase_initialize_autoinc();
            }
    
            dict_table_autoinc_unlock(prebuilt->table);
        }
    
        info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
    
        DBUG_RETURN(0);
    }
    /************************************************************************//**
     Handling the shared INNOBASE_SHARE structure that is needed to provide table
     locking.
    ****************************************************************************/
    
    static INNOBASE_SHARE* get_share(const char* table_name)
    {
        INNOBASE_SHARE *share;
        mysql_mutex_lock(&innobase_share_mutex);
    
        ulint    fold = ut_fold_string(table_name);
    
        HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
                INNOBASE_SHARE*, share,
                ut_ad(share->use_count > 0),
                !strcmp(share->table_name, table_name));
    
        if (!share) {
    
            uint length = (uint) strlen(table_name);
    
            /* TODO: invoke HASH_MIGRATE if innobase_open_tables
            grows too big */
    
            share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
                MYF(MY_FAE | MY_ZEROFILL));
    
            share->table_name = (char*) memcpy(share + 1,
                               table_name, length + 1);
    
            HASH_INSERT(INNOBASE_SHARE, table_name_hash,
                    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++;
        mysql_mutex_unlock(&innobase_share_mutex);
    
        return(share);
    }
  • 相关阅读:
    STM32+ESP8266+AIR202基本控制篇-301-服务器单向SSL认证-MQTT服务器配置SSL单向认证(.Windows系统)
    STM32+ESP8266+AIR202基本控制篇-213-功能测试-微信小程序扫码绑定Air302(NB-IOT),并通过MQTT和Air302(NB-IOT)实现远程通信控制
    17-STM32+ESP8266+AIR202基本控制篇-完成功能2-微信小程序使用APUConfig配网绑定ESP8266,并通过MQTT和ESP8266实现远程通信控制
    Python 元类
    硬核!15张图解Redis为什么这么快
    Protobuf 中 any 的妙用
    Grpc性能压测方法:用ghz进行压测
    压测工具Locuse的使用
    Locust 多机器分布式测试
    kubespray部署kubernetes高可用集群
  • 原文地址:https://www.cnblogs.com/taek/p/5071191.html
Copyright © 2011-2022 走看看