MySQL表frm文件解析

MySQL表frm文件解析

    • MySQL .frm文件格式

说明:
以下所有说明都以 MySQL 5.7.25 源码为例 ,存储引擎为InnoDB。

MySQL .frm文件格式

MySQL会为每一个table在磁盘上创建一个.frm格式尾缀的文件,作为表定义文件,该文件与表名一致。

首先,创建一个表:

mysql> create table t1 (
 a int not null comment 'comment on column a',
 b int default 5 comment 'comment on column b',
 primary key(a),
 key idx_a(a),
 key idx_b(b),
 key idx_a_b(a,b),
 key idx_b_comment(b) comment 'comment on key b'
 ) engine = innodb;

每个表的.frm文件会在mysql安装的data目录下,可以查看变量datadir查看具体路径。

mysql> select @@datadir;
+--------------------------------------------------+
| @@datadir                                        |
+--------------------------------------------------+
| /opt/mysql/mysql-5.7.25/mysql/data/              |
+--------------------------------------------------+

确定table的具体database

mysql> select database();
+--------------------+
| database()         |
+--------------------+
| innodb             |
+--------------------+

每个databasetable.frm文件会创建在datadir/database_name/路径下,进入/opt/mysql/mysql-5.7.25/mysql/data/ innodb可以查看到:

shell> su root
shell> cd /opt/mysql/mysql-5.7.25/mysql/data/ innodb
shell> ls t1.*
  table1.frm  table1.MYD  table1.MYI
shell> ls -l t1.*
-rw-rw----  1 root root  8578 May 28 20:31 t1.frm
-rw-rw----  1 root root 98304 May 28 20:31 t1.ibd

使用vi打开并且切换到命令模式,输入!xxd -g 1即可查看单字节的十六进制编码结果,也可以用hexdump查看。
MySQL表frm文件解析_第1张图片
表1 .frm 文件头部 Header 段区域

Tips:
下列表格属性说明:

  • 偏移:.frm文件头偏移量
  • 长度:字节个数
  • 值:属性值
  • 描述:简明描述
偏移 长度 描述
0000 1 FE 固定值
0001 1 01 固定值
0002 1 09 FRM_VER+3+ MY_TEST(create_info->varchar)
FRM_VER(6) (#define FRM_VER @DOT_FRM_VERSION@) )
DOT_FRM_VERSION(cmake/mysql_version.cmake) SET(DOT_FRM_VERSION “6”)
0003 1 0c InnoDB引擎(DB_TYPE数据库引擎类型,enum legacy_db_type)
0004 1 03 固定值 (代码中0x01)
0005 1 00 固定值
0006 2 0010 IO_SIZE(拼成:0x1000=4096)
0008 2 0100
000a 4 00300000 (IO_SIZE+key_length+reclength+ create_info->extra_size)
000e 2 df06 tmp_key_length=key_length(key_length的计算公式在表格下方 )
0010 2 0900 reclength
0012 4 00000000 create_info->max_rows
0016 4 00000000 create_info->min_rows
001B 1 02 固定值(Use long pack-fields)
001C 2 a200 key_info_length
001e 2 0800 create_info->table_options also known as db_create_options? one possible option is HA_LONG_BLOB_PTR
0020 1 00 固定值
0021 1 05 固定值(Mark for 5.0 frm file)
0022 4 00000000 create_info->avg_row_length
0026 1 2e create_info->default_table_charset (utf8mb4)
0027 1 00 固定值
0028 1 00 create_info->row_type
0029 6 00…00 固定值(RAID support)
002f 4 df060000 key_length
0033 4 25c600 MYSQL_VERSION_ID(50725[C625])mysql_version.h
0037 4 1f000000 create_info->extra_size
003b 2 0000 Reserved for extra_rec_buf_length
003d 1 00 Reserved for default_part_db_type, but 09 if MyISAM with partitioning
003e 2 0000 create_info->key_block_size
0040

key_length = keys * (8 + MAX_REF_PARTS * 9 + NAME_LEN + 1) + 16 + key_comment_total_bytes

  • 每一个索引:
    8位作为key header
    9位留给每一个索引的每一个列field
    NAME_LEN为索引索引名称
    最后的16代表:6位作为header,1位作为分隔符’\0’,9位预留?对齐?

  • keys: 表索引个数

  • MAX_REF_PARTS: 单个索引支持最多列数(16个)

  • NAME_LEN: =(NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN)
    NAME_CHAR_LEN: 64位,表名、列名长度
    SYSTEM_CHARSET_MBMAXLEN: 3,系统字符集最大长度
    key_comment_total_bytes: 16,无comment

所以key_length = 5*(8+16*9+64*3+1)+16+16 + 2 = 706 = 0x6df

表2 .frm 索引 Key 信息段区域
根据头部 Header 信息中的 0004 中的 IO_SIZE 作偏移一个 IO_SIZE,即为索引 keys 信息区域。
此处 IO_SIZE 大小为 4096;

偏移 长度 描述
1000 1 05 索引个数,此处为有 5 个索引
1000 1 06 索引列数目,总共 5 个索引有 6 个索引列

你可能感兴趣的:(MySQL)