首页 > 数据库 > MySQL > 正文

mysql的frm文件报错如何修复

2024-07-24 12:33:30
字体:
来源:转载
供稿:网友
  在mysql中,frm的意思为“表定义”,是描述数据表结构的文件。
 
  MySQL通过sql/table.cc的create_frm()函数创建frm文件,创建出来的frm文件是二进制文件,需要通过hexdump解析成16进制来分析。
 
  create_frm()函数对frm文件头部定义的代码
 
  /* Create a .frm file */
 
  File create_frm(THD *thd, const char *name, const char *db,
                  const char *table, uint reclength, uchar *fileinfo,
            HA_CREATE_INFO *create_info, uint keys, KEY *key_info)
  {
    register File file;
    ulong length;
    uchar fill[IO_SIZE];
    int create_flags= O_RDWR | O_TRUNC;
    ulong key_comment_total_bytes= 0;
    uint i;
 
    if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
      create_flags|= O_EXCL | O_NOFOLLOW;
 
    /* Fix this when we have new .frm files;  Current limit is 4G rows (QQ) */
    if (create_info->max_rows > UINT_MAX32)
      create_info->max_rows= UINT_MAX32;
    if (create_info->min_rows > UINT_MAX32)
      create_info->min_rows= UINT_MAX32;
 
    if ((file= mysql_file_create(key_file_frm,
                                 name, CREATE_MODE, create_flags, MYF(0))) >= 0)
    {
      uint key_length, tmp_key_length, tmp, csid;
      bzero((char*) fileinfo,64);
      /* header */
      fileinfo[0]=(uchar) 254;
      fileinfo[1]= 1;
      fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
 
      fileinfo[3]= (uchar) ha_legacy_type(
            ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0));
      fileinfo[4]=1;
      int2store(fileinfo+6,IO_SIZE);        /* Next block starts here */
      /*
        Keep in sync with pack_keys() in unireg.cc
        For each key:
        8 bytes for the key header
        9 bytes for each key-part (MAX_REF_PARTS)
        NAME_LEN bytes for the name
        1 byte for the NAMES_SEP_CHAR (before the name)
        For all keys:
        6 bytes for the header
        1 byte for the NAMES_SEP_CHAR (after the last name)
        9 extra bytes (padding for safety? alignment?)
      */
      for (i= 0; i < keys; i++)
      {
        DBUG_ASSERT(test(key_info[i].flags & HA_USES_COMMENT) ==
                   (key_info[i].comment.length > 0));
        if (key_info[i].flags & HA_USES_COMMENT)
          key_comment_total_bytes += 2 + key_info[i].comment.length;
      }
 
      key_length= keys * (8 + MAX_REF_PARTS * 9 + NAME_LEN + 1) + 16
                  + key_comment_total_bytes;
 
      length= next_io_size((ulong) (IO_SIZE+key_length+reclength+
                                    create_info->extra_size));
      int4store(fileinfo+10,length);
      tmp_key_length= (key_length < 0xffff) ? key_length : 0xffff;
      int2store(fileinfo+14,tmp_key_length);
      int2store(fileinfo+16,reclength);
      int4store(fileinfo+18,create_info->max_rows);
      int4store(fileinfo+22,create_info->min_rows);
      /* fileinfo[26] is set in mysql_create_frm() */
      fileinfo[27]=2;                // Use long pack-fields
      /* fileinfo[28 & 29] is set to key_info_length in mysql_create_frm() */
      create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers
      int2store(fileinfo+30,create_info->table_options);
      fileinfo[32]=0;                // No filename anymore
      fileinfo[33]=5;                             // Mark for 5.0 frm file
      int4store(fileinfo+34,create_info->avg_row_length);
      csid= (create_info->default_table_charset ?
             create_info->default_table_charset->number : 0);
      fileinfo[38]= (uchar) csid;
      /*
        In future versions, we will store in fileinfo[39] the values of the
        TRANSACTIONAL and PAGE_CHECKSUM clauses of CREATE TABLE.
      */
      fileinfo[39]= 0;
      fileinfo[40]= (uchar) create_info->row_type;
      /* Next few bytes where for RAID support */
      fileinfo[41]= (uchar) (csid >> 8);
      fileinfo[42]= 0;
      fileinfo[43]= 0;
      fileinfo[44]= 0;
      fileinfo[45]= 0;
      fileinfo[46]= 0;
      int4store(fileinfo+47, key_length);
      tmp= MYSQL_VERSION_ID;          // Store to avoid warning from int4store
      int4store(fileinfo+51, tmp);
      int4store(fileinfo+55, create_info->extra_size);
      /*
        59-60 is reserved for extra_rec_buf_length,
        61 for default_part_db_type
      */
      int2store(fileinfo+62, create_info->key_block_size);
      bzero(fill,IO_SIZE);
      for (; length > IO_SIZE ; length-= IO_SIZE)
      {
        if (mysql_file_write(file, fill, IO_SIZE, MYF(MY_WME | MY_NABP)))
        {
          (void) mysql_file_close(file, MYF(0));
          (void) mysql_file_delete(key_file_frm, name, MYF(0));
      return(-1);
        }
      }
    }
    else
    {
      if (my_errno == ENOENT)
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
      else
        my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
    }
    return (file);
  } /* create_frm */
  open_binary_frm()函数对对frm索引部分定义的代码
 
  for (i=0 ; i < keys ; i++, keyinfo++)
    {
      keyinfo->table= 0;                           // Updated in open_frm
      if (new_frm_ver >= 3)
      {
        keyinfo->flags=       (uint) uint2korr(strpos) ^ HA_NOSAME;
        keyinfo->key_length= (uint) uint2korr(strpos+2);
        keyinfo->key_parts=  (uint) strpos[4];
        keyinfo->algorithm=  (enum ha_key_alg) strpos[5];
        keyinfo->block_size= uint2korr(strpos+6);
        strpos+=8;
      }
      else
      {
        keyinfo->flags=     ((uint) strpos[0]) ^ HA_NOSAME;
        keyinfo->key_length= (uint) uint2korr(strpos+1);
        keyinfo->key_parts=  (uint) strpos[3];
        keyinfo->algorithm= HA_KEY_ALG_UNDEF;
        strpos+=4;
      }
 
      keyinfo->key_part=     key_part;
      keyinfo->rec_per_key= rec_per_key;
      for (j=keyinfo->key_parts ; j-- ; key_part++)
      {
        *rec_per_key++=0;
        key_part->fieldnr=    (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
        key_part->offset= (uint) uint2korr(strpos+2)-1;
        key_part->key_type=    (uint) uint2korr(strpos+5);
        // key_part->field=    (Field*) 0;    // Will be fixed later
        if (new_frm_ver >= 1)
        {
      key_part->key_part_flag= *(strpos+4);
      key_part->length=    (uint) uint2korr(strpos+7);
      strpos+=9;
        }
        else
        {
      key_part->length=    *(strpos+4);
      key_part->key_part_flag=0;
      if (key_part->length > 128)
      {
        key_part->length&=127;        /* purecov: inspected */
        key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
      }
      strpos+=7;
        }
        key_part->store_length=key_part->length;
      }
    }
    keynames=(char*) key_part;
    strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
 
    //reading index comments
    for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
    {
      if (keyinfo->flags & HA_USES_COMMENT)
      {
        keyinfo->comment.length= uint2korr(strpos);
        keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
                                           keyinfo->comment.length);
        strpos+= 2 + keyinfo->comment.length;
      }
      DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) ==
                 (keyinfo->comment.length > 0));
    }
  hexdump是Linux下的一个二进制文件查看工具,可以将二进制文件转换为ASCII、10进制、16进制或8进制进行查看。

(编辑:武林网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表