我理解的MYISAM引擎之七 check、analyze、optimize、repair 与myisamchk

 

语句 参数 作用 引擎 备注
CHECK TABLE FOR UPGRADE 检查升级后的不兼容项 MYISAM,INNODB,VIEW a)选项可以叠加使用,从上往下,校验的内容逐渐增多;
b)check table会自动flush table;
c)   check  table如果在innodb上发现了非2级索引的块损坏,会导致mysqld进程崩溃https://bugs.mysql.com/bug.php?id=10132
d)   对于innodb,check table 可以并行读取cluster index,并行读取值为min( innodb_parallel_read_threads setting ,the number of index subtree)
e)   对于MYISAM,check table会更新统计信息,如果没有指定QUICK或者MEDIUM或者EXTEND,默认选项为MEDIUM
f)    验证delete连接的逻辑:MYI文件中的文件从37字节开始的8个字节记录了此表中被标记删除的记录,接下来的8个字节记录了MYD文件中被标记删除的记录占用的空间,再接下来的8个字节记录了MYD文件中最后一个删除记录的偏移地址,通过这个地址在MYD可以找到最后一个被删除的记录。同时,每一个被删除的记录保存了上一个被删除和下一个被删除的记录的双向链表、当前被删除记录占用空间大小三个数据,删除校验的目的就是从链表的头开始一个一个检查对应的前后链接的有效性,以及将所有删除记录记录的删除空间累加,直到链表尾部,最终此空间累积和大小需要等于MYI文件中记录的大小。
对于dynamic格式的myisam表,每一个被删除的记录元数据信息在记录开始的20个字节中,其中,第一个字节为标记位,00表示标记删除,接下来的3字节表示此标记删除记录占用空间大小,接下来的8字节记录了下一个标记删除记录的偏移地址,最后的8字节记录了上一个标记删除记录的偏移地址;
对于fix格式的myisam表,由于行长度固定(MYI文件头261字节开始的4个字节记录了行长度pack_reclength),因此MYD中记录的寻址是通过行号*每行记录所占空间大小来确定偏移地址的。删除链表的前后指针均指行号,单行删除空间即为行大小,累积删除空间等于删除行数*每行所占空间。MYI文件第285字节记录了rec_reflength值,也既行号所占字节数,此记录从2-8个字节不等,由参数myisam_data_pointer_size控制,当然这个值的范围是2-7,少了一个字节。
g) EXTENDED与MEDIUM相比,多了扫描全部行的所有索引key的步骤;
h)MEDIUM与CHANGED相比,仅去掉了CHANGED的前置条件,检查内容一致;
j)QUICK的不扫描行体现在check方法中的判断,如果没有指定(显示或隐式)QUICK的话,会调用mi_check.cc的check_data_link方法,此方法中会读取整个MYD文件,并校验数据、计算校验和。这也是QUICK与CHANGED、MEDIUM、EXTENDED比起来少了的地方;
k)FOR UPGRADE在8.0版本上是自动检查项了,无论做什么检查,都会顺带进行。
l)对于dynamic行格式,如果没有指定QUICK, MEDIUM, or EXTENDED 选项,则默认执行medium检查;对于static行格式,如没有指定任何选项,则默认执行medium检查,CHANGED与QUICK的检查项相同;
m)从这一段代码可以看出,特定情况下,fast到这里就结束返回了:
下面这两端代码均出自ha_myisam.cc文件的int ha_myisam::check(THD *thd, HA_CHECK_OPT *check_opt)方法
  if (!mi_is_crashed(file) &&
      (((param.testflag & T_CHECK_ONLY_CHANGED) &&
        !(share->state.changed &
          (STATE_CHANGED | STATE_CRASHED | STATE_CRASHED_ON_REPAIR)) &&
        share->state.open_count == 0) ||
       ((param.testflag & T_FAST) &&
        (share->state.open_count == (uint)(share->global_changed ? 1 : 0)))))
    return HA_ADMIN_ALREADY_DONE;
而后面还会有下面这些检查。这些也是fast与CHANGED/MEDIUM/EXTENDED等相比缺少的检查:
error = chk_status(¶m, file);  // Not fatal
  error = chk_size(¶m, file);
  if (!error) error |= chk_del(¶m, file, param.testflag);
  if (!error) error = chk_key(¶m, file);
  if (!error) {
    if ((!(param.testflag & T_QUICK) &&
         ((share->options &
           (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
        mi_is_crashed(file)) {
      uint old_testflag = param.testflag;
      param.testflag |= T_MEDIUM;
      if (!(error = init_io_cache(
                ¶m.read_cache, file->dfile, my_default_record_cache_size,
                READ_CACHE, share->pack.header_length, true, MYF(MY_WME)))) {
        error = chk_data_link(¶m, file, param.testflag & T_EXTEND);
        end_io_cache(&(param.read_cache));
      }
      param.testflag = old_testflag;
    }
  }
h)MEDIUM与EXTENDED主要的不同在mi_check.cc中的int chk_data_link(MI_CHECK *param, MI_INFO *info, int extend)方法的第1151行代码
if (extend) {
              /* We don't need to lock the key tree here as we don't allow
                 concurrent threads when running myisamchk
              */
              int search_result =
                  (keyinfo->flag & HA_SPATIAL)
                      ? rtree_find_first(info, key, info->lastkey, key_length,
                                         MBR_EQUAL | MBR_DATA)
                      : _mi_search(info, keyinfo, info->lastkey, key_length,
                                   SEARCH_SAME, info->s->state.key_root[key]);
              if (search_result) {
                mi_check_print_error(param,
                                     "Record at: %10s  "
                                     "Can't find key for index: %2d",
                                     llstr(start_recpos, llbuff), key + 1);
                if (error++ > MAXERR || !(param->testflag & T_VERBOSE))
                  goto err2;
              }
            } else
              key_checksum[key] +=
                  mi_byte_checksum((uchar *)info->lastkey, key_length);
QUICK 不扫描行 MYISAM,  INNODB
FAST 仅检查没有正常close的表 MYISAM,  VIEW
CHANGED 仅检查自上一次check后有变化的表
和没有正常close的表
MYISAM,  VIEW
MEDIUM 根据delete_link扫描MYD数据行行以验证被标记为deleted的链接是否有效,
会分别计算数据行中的key值和索引文件中的key的校验和,并进行比较是否相同。
默认选项。

 
MYISAM,  VIEW
EXTENDED 将MEDIUM的计算校验和验证数据的方式,换成了扫描所有索引key全部行记录的方式。 MYISAM,  VIEW
checksum QUICK 当表属性CHECKSUM=1时,返回已保存的checnsum值
如果指定quick,但是checksum不为1,那么返回NULL
MYISAM, a) 用于计算整表的校验和数据,用来对数据迁移前后的表数据完整性进行校验
b) 由于校验和算法问题,实际不同的表内容可能得出相同的校验和,但是不同的校验和,表内容一定不同
EXTENDED 实时的一行一行的读取并计算校验和 MYISAM,  INNODB
         
analyze    收集表统计信息,   收集统计信息,统计信息结果收集后存储在information_schema.tables、information_schema.statistics、information_schema.COLUMN_STATISTICS(列直方图)、information_schema.STATISTICS、information_schema.INNODB_TABLESTATS
         
optimize   重建表。重新组织表数据。释放表文件空间。 常规支持:MYISAM,INNODB,NDB 1,对于MYISAM引擎:消除碎片,排序索引block,更新统计信息;
2,对于innodb:释放多余空间。大量删除数据后,将磁盘空间释放回操作系统。默认使用online ddl ,alter table .. Force. 如果启用skip-new或者 old_alter_table选项,则使用table  copy方法。
3,不支持空间索引。
skip-new启用后可以支持其他存储引擎。实际转换为alter table。
         
repair table QUICK 只repaired索引数据。支持分区表; MYISAM、CSV、ARCHIVE upgrade升级表,修复损坏的索引,表数据,
2,NO_WRITE_TO_BINLOG、LOCAL不记录repair table到binglog中。注意与repair table对源表的修改内容不会同步到从库做区分;
3,USE_FRM,因为MYI文件header保存了MYISAM表的大量元数据,不使用MYI文件头,会导致依赖此部分信息的数据丢失,具体如下:
     a)自增列最大值丢失;
     b)delete_link丢失,导致MYD文件中已标记为删除的空间不能重用;
     c)MYI文件头首4个字节标志了文件版本,不使用这个信息,导致repair table不会进行upgrade检查升级;
     d)MYI文件中标记了表是否是compress格式,因此对于压缩格式的表,会解析文件失败。(但是compress格式的表都是只读的,会用到repair的机会渺茫)
     e)如果使用了与表文件不同版本的repair,会报错。
4,如果设置了avoid_temporal_upgrade 系统变量,则repair不会upgrade表。
5,可通过设置 myisam_max_sort_file_size 、key_buffer_size、myisam_sort_buffer_size、read_buffer_size等系统变量值提高repair效率。
EXTENDED repair索引和数据。支持分区表;
USE_FRM repair索引和数据。但是忽略MYI文件header。仅使用数据字典存储的表元数据。 MYISAM

此外,MYISAMCHK工具集成了check,analyze,optimize,repair功能于一身,还多了其他功能:

1,按照特定索引顺序排序对应的MYD记录,以增强按照特定索引排序的顺序读性能。-R, --sort-records=#
2,解压myisampack压缩的文件。-u, --unpack
3,设置自增列的值。-A, --set-auto-increment[=value]。自增列的值保存在MYI文件头中。
4,发现特定block中的记录。-b,  --block-search=#
5,当MYD满了之后(达到建表时指定的最大文件大小),可以通过重建的方式增大最大大小。-D, --data-file-length=#
6,repair时,仅修改特定索引。-k, --keys-used=#
7,repair时,可自动备份。-B, --backup

myisamchk的全部选项可通过myisamchk --help查看。具体使用时,可设置如下内存参数加快性能,最好设置tmp目录指向其他目录,因为默认的tmpdir使用的是linux操作系统的内存文件系统,相当于完全内存操作。可能造成主机内存不足。
tmpdir                            (No default value)
key-buffer-size                   520192
read-buffer-size                  262136
write-buffer-size                 262136
sort-buffer-size                  2097144
myisam-sort-buffer-size           2097144
sort-key-blocks                   16

需要注意的是,myisamchk在检查带有MYI后缀的文件时,会有报错myisamchk: error: 140 when opening MyISAM-table 。这是个历史悠久的BUG。https://bugs.mysql.com/bug.php?id=87729
可以这样搞一下:
ls *.MYI | xargs basename -s .MYI|xargs  -I{}  /usr/local/mysql/mysql-5.7.27-el7-x86_64/bin/myisamchk -c -s -s

你可能感兴趣的:(mysql)