mysql 5.6版本分区表有一个文件:表名.par, 该文件在5.7.6版本后被移除。
在一个现场环境中,客户端执行check table后报错如下,源码跟踪下来之后是缺失par文件。
mysql解析par文件的调用堆栈如下:
(gdb) bt
#0 ha_partition::read_par_file (this=0x7fff980aa760, name=0x7fff98098be0 "./envision/tbl_pointvalue_10m") at /home/windos/mysql-5.6.41/sql/ha_partition.cc:2816:最终解析.par文件的函数,par文件具体格式见后文
#1 0x0000000000e3c595 in ha_partition::get_from_handler_file (this=0x7fff980aa760, name=0x7fff98098be0 "./envision/tbl_pointvalue_10m", mem_root=0x7fff980988c8, is_clone=false) at /home/windos/mysql-5.6.41/sql/ha_partition.cc:2968
#2 0x0000000000e36636 in ha_partition::initialize_partition (this=0x7fff980aa760, mem_root=0x7fff980988c8) at /home/windos/mysql-5.6.41/sql/ha_partition.cc:511
#3 0x0000000000e35b87 in partition_create_handler (hton=0x23b8f80, share=0x7fff98098860, mem_root=0x7fff980988c8) at /home/windos/mysql-5.6.41/sql/ha_partition.cc:193
#4 0x000000000064ff38 in get_new_handler (share=0x7fff98098860, alloc=0x7fff980988c8, db_type=0x23b8f80) at /home/windos/mysql-5.6.41/sql/handler.cc:442:根据db_type创建handler成员,在该示例中为ha_patition,调用该成员的init函数
#5 0x00000000008ba190 in open_binary_frm (thd=0x244e720, share=0x7fff98098860, head=0x7fffceb1ae40 "\376\001\n\024\003", file=78) at /home/windos/mysql-5.6.41/sql/table.cc:1569
#6 0x00000000008b77af in open_table_def (thd=0x244e720, share=0x7fff98098860, db_flags=8192) at /home/windos/mysql-5.6.41/sql/table.cc:746:读frm文件,如果是普通类型的表,调用open_binary_frm
#7 0x0000000000782def in get_table_share (thd=0x244e720, table_list=0x7fff98006ea0, key=0x7fff98007265 "envision", key_length=28, db_flags=8192, error=0x7fffceb1b2b4, hash_value=1766698362) at /home/windos/mysql-5.6.41/sql/sql_base.cc:503 :从缓存中查找share对象,找不到读frm文件新建
#8 0x00000000007831a3 in get_table_share_with_discover (thd=0x244e720, table_list=0x7fff98006ea0, key=0x7fff98007265 "envision", key_length=28, db_flags=8192, error=0x7fffceb1b2b4, hash_value=1766698362) at /home/windos/mysql-5.6.41/sql/sql_base.cc:583
#9 0x000000000078834a in open_table (thd=0x244e720, table_list=0x7fff98006ea0, ot_ctx=0x7fffceb1b470) at /home/windos/mysql-5.6.41/sql/sql_base.cc:3034:打开表,先从缓存中查找,查找不到新建表对象
#10 0x000000000078b0a7 in open_and_process_table (thd=0x244e720, lex=0x24505b0, tables=0x7fff98006ea0, counter=0x7fffceb1b5a4, flags=0, prelocking_strategy=0x7fffceb1b5f0, has_prelocking_list=false, ot_ctx=0x7fffceb1b470) at /home/windos/mysql-5.6.41/sql/sql_base.cc:4732
#11 0x000000000078bd47 in open_tables (thd=0x244e720, start=0x7fffceb1b560, counter=0x7fffceb1b5a4, flags=0, prelocking_strategy=0x7fffceb1b5f0) at /home/windos/mysql-5.6.41/sql/sql_base.cc:5165
#12 0x000000000078cdbf in open_and_lock_tables (thd=0x244e720, tables=0x7fff98006ea0, derived=true, flags=0, prelocking_strategy=0x7fffceb1b5f0) at /home/windos/mysql-5.6.41/sql/sql_base.cc:5818
#13 0x000000000077e4d6 in open_and_lock_tables (thd=0x244e720, tables=0x7fff98006ea0, derived=true, flags=0) at /home/windos/mysql-5.6.41/sql/sql_base.h:472
#14 0x00000000009b32b7 in mysql_admin_table (thd=0x244e720, tables=0x7fff98006ea0, check_opt=0x2451368, operator_name=0xfcf9e4 "check", lock_type=TL_READ_NO_INSERT, open_for_modify=false, repair_table_use_frm=false, extra_open_options=32, prepare_func=0, operator_func=(int (handler::*)(handler *, THD *, HA_CHECK_OPT *)) 0x6581be
#15 0x00000000009b5b5d in Sql_cmd_check_table::execute (this=0x7fff98007410, thd=0x244e720) at /home/windos/mysql-5.6.41/sql/sql_admin.cc:1102 : 执行check table命令后程序的入口函数
#16 0x00000000007fe04a in mysql_execute_command (thd=0x244e720) at /home/windos/mysql-5.6.41/sql/sql_parse.cc:4995
#17 0x0000000000801676 in mysql_parse (thd=0x244e720, rawbuf=0x7fff98006d90 "check table tbl_pointvalue_10m", length=30, parser_state=0x7fffceb1d670) at /home/windos/mysql-5.6.41/sql/sql_parse.cc:6422
#18 0x00000000007f42ac in dispatch_command (command=COM_QUERY, thd=0x244e720, packet=0x25226b1 "", packet_length=30) at /home/windos/mysql-5.6.41/sql/sql_parse.cc:1399
#19 0x00000000007f3296 in do_command (thd=0x244e720) at /home/windos/mysql-5.6.41/sql/sql_parse.cc:1064
#20 0x00000000007b9191 in do_handle_one_connection (thd_arg=0x244e720) at /home/windos/mysql-5.6.41/sql/sql_connect.cc:982
#21 0x00000000007b8f26 in handle_one_connection (arg=0x244e720) at /home/windos/mysql-5.6.41/sql/sql_connect.cc:899
#22 0x0000000000e22d44 in pfs_spawn_thread (arg=0x245a2b0) at /home/windos/mysql-5.6.41/storage/perfschema/pfs.cc:1861
#23 0x00000033f1207aa1 in start_thread () from /lib64/libpthread.so.0
#24 0x00000033f0ae8aad in clone () from /lib64/libc.so.6
(gdb)
read_par_file函数中可以看到par文件格式如下所示:
0-4字节:文件的长度len_words,单位是word(4个字节), 该数值*4是整个文件的字节长度
4-8字节:一个校验值,把len_words的整数进行异或运算,值为0
8-12字节:分区表的数量pa_num, 决定了下一个部分的长度
12- ?字节:该段的长度为pa_num 长度,不足4字节的补足4字节, eg:pa_num为21,占用的24字节
每个分区用一个字节存储类型
分区表的名称长度:不足4字节补全4字节
每个分区的名称