1. 程式人生 > >mysql .par檔案格式解析

mysql .par檔案格式解析

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 <handler::ha_check(THD*, HA_CHECK_OPT*)>, view_operator_func=0x8965dc <view_checksum(THD*, TABLE_LIST*)>) at /home/windos/mysql-5.6.41/sql/sql_admin.cc:400
#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位元組

每個分割槽的名稱