MySQL 8.0.46
Source Code Documentation
mi_check.cc File Reference
#include "my_config.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <sys/types.h>
#include <time.h>
#include <algorithm>
#include "m_ctype.h"
#include "my_byteorder.h"
#include "my_compiler.h"
#include "my_dbug.h"
#include "my_double2ulonglong.h"
#include "my_getopt.h"
#include "my_inttypes.h"
#include "my_io.h"
#include "my_macros.h"
#include "my_pointer_arithmetic.h"
#include "storage/myisam/ftdefs.h"
#include "storage/myisam/myisam_sys.h"
#include <sys/mman.h>
#include "storage/myisam/rt_index.h"

Functions

static int check_k_link (MI_CHECK *param, MI_INFO *info, uint nr)
 
static int chk_index (MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, ha_checksum *key_checksum, uint level)
 
static uint isam_key_length (MI_INFO *info, MI_KEYDEF *keyinfo)
 
static ha_checksum calc_checksum (ha_rows count)
 
static int writekeys (MI_SORT_PARAM *sort_param)
 
static int sort_one_index (MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pagepos, File new_file)
 
static int sort_key_read (MI_SORT_PARAM *sort_param, void *key)
 
static int sort_ft_key_read (MI_SORT_PARAM *sort_param, void *key)
 
static int sort_get_next_record (MI_SORT_PARAM *sort_param)
 
static int sort_key_cmp (void *cmp_arg, unsigned char *a, unsigned char *b)
 
static int sort_ft_key_write (MI_SORT_PARAM *sort_param, const void *a)
 
static int sort_key_write (MI_SORT_PARAM *sort_param, const void *a)
 
static my_off_t get_record_for_key (MI_INFO *info, MI_KEYDEF *keyinfo, const uchar *key)
 
static int sort_insert_key (MI_SORT_PARAM *sort_param, SORT_KEY_BLOCKS *key_block, const uchar *key, my_off_t prev_block)
 
static int sort_delete_record (MI_SORT_PARAM *sort_param)
 
static SORT_KEY_BLOCKS * alloc_key_blocks (MI_CHECK *param, uint blocks, uint buffer_length)
 
static ha_checksum mi_byte_checksum (const uchar *buf, uint length)
 
static void set_data_file_type (SORT_INFO *sort_info, MYISAM_SHARE *share)
 
static HA_KEYSEG * ha_find_null (HA_KEYSEG *keyseg, const uchar *a)
 
void myisamchk_init (MI_CHECK *param)
 
int chk_status (MI_CHECK *param, MI_INFO *info)
 
int chk_del (MI_CHECK *param, MI_INFO *info, uint test_flag)
 
int chk_size (MI_CHECK *param, MI_INFO *info)
 
int chk_key (MI_CHECK *param, MI_INFO *info)
 
static int chk_index_down (MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, ha_checksum *key_checksum, uint level)
 
static void mi_collect_stats_nonulls_first (HA_KEYSEG *keyseg, ulonglong *notnull, const uchar *key)
 
static int mi_collect_stats_nonulls_next (HA_KEYSEG *keyseg, ulonglong *notnull, uchar *prev_key, const uchar *last_key)
 
int chk_data_link (MI_CHECK *param, MI_INFO *info, int extend)
 
static int mi_drop_all_indexes (MI_CHECK *param, MI_INFO *info, bool force)
 Drop all indexes. More...
 
int mi_repair (MI_CHECK *param, MI_INFO *info, char *name, int rep_quick, bool no_copy_stat)
 
int movepoint (MI_INFO *info, uchar *record, my_off_t oldpos, my_off_t newpos, uint prot_key)
 
int flush_blocks (MI_CHECK *param, KEY_CACHE *key_cache, File file)
 
int mi_sort_index (MI_CHECK *param, MI_INFO *info, char *name, bool no_copy_stat)
 
int change_to_newfile (const char *filename, const char *old_ext, const char *new_ext, myf MyFlags)
 
int lock_file (MI_CHECK *param, File file, int lock_type, const char *filetype, const char *filename)
 
int filecopy (MI_CHECK *param, File to, File from, my_off_t start, my_off_t length, const char *type)
 
int mi_repair_by_sort (MI_CHECK *param, MI_INFO *info, const char *name, int rep_quick, bool no_copy_stat)
 
int sort_write_record (MI_SORT_PARAM *sort_param)
 
int sort_ft_buf_flush (MI_SORT_PARAM *sort_param)
 
int flush_pending_blocks (MI_SORT_PARAM *sort_param)
 
int test_if_almost_full (MI_INFO *info)
 
int recreate_table (MI_CHECK *param, MI_INFO **org_info, char *filename)
 
int write_data_suffix (SORT_INFO *sort_info, bool fix_datafile)
 
int update_state_info (MI_CHECK *param, MI_INFO *info, uint update)
 
void update_auto_increment_key (MI_CHECK *param, MI_INFO *info, bool repair_only)
 
void update_key_parts (MI_KEYDEF *keyinfo, ulong *rec_per_key_part, ulonglong *unique, ulonglong *notnull, ulonglong records)
 
static bool mi_too_big_key_for_sort (MI_KEYDEF *key, ha_rows rows)
 
void mi_disable_non_unique_index (MI_INFO *info, ha_rows rows)
 
bool mi_test_if_sort_rep (MI_INFO *info, ha_rows rows, ulonglong key_map, bool force)
 

Function Documentation

◆ alloc_key_blocks()

static SORT_KEY_BLOCKS * alloc_key_blocks ( MI_CHECK *  param,
uint  blocks,
uint  buffer_length 
)
static

◆ calc_checksum()

static ha_checksum calc_checksum ( ha_rows  count)
static

◆ change_to_newfile()

int change_to_newfile ( const char *  filename,
const char *  old_ext,
const char *  new_ext,
myf  MyFlags 
)

◆ check_k_link()

static int check_k_link ( MI_CHECK *  param,
MI_INFO *  info,
uint  nr 
)
static

◆ chk_data_link()

int chk_data_link ( MI_CHECK *  param,
MI_INFO *  info,
int  extend 
)

◆ chk_del()

int chk_del ( MI_CHECK *  param,
MI_INFO *  info,
uint  test_flag 
)

◆ chk_index()

static int chk_index ( MI_CHECK *  param,
MI_INFO *  info,
MI_KEYDEF *  keyinfo,
my_off_t  page,
uchar *  buff,
ha_rows *  keys,
ha_checksum *  key_checksum,
uint  level 
)
static

◆ chk_index_down()

static int chk_index_down ( MI_CHECK *  param,
MI_INFO *  info,
MI_KEYDEF *  keyinfo,
my_off_t  page,
uchar *  buff,
ha_rows *  keys,
ha_checksum *  key_checksum,
uint  level 
)
static

◆ chk_key()

int chk_key ( MI_CHECK *  param,
MI_INFO *  info 
)

◆ chk_size()

int chk_size ( MI_CHECK *  param,
MI_INFO *  info 
)

◆ chk_status()

int chk_status ( MI_CHECK *  param,
MI_INFO *  info 
)

◆ filecopy()

int filecopy ( MI_CHECK *  param,
File  to,
File  from,
my_off_t  start,
my_off_t  length,
const char *  type 
)

◆ flush_blocks()

int flush_blocks ( MI_CHECK *  param,
KEY_CACHE *  key_cache,
File  file 
)

◆ flush_pending_blocks()

int flush_pending_blocks ( MI_SORT_PARAM *  sort_param)

◆ get_record_for_key()

static my_off_t get_record_for_key ( MI_INFO *  info,
MI_KEYDEF *  keyinfo,
const uchar *  key 
)
static

◆ ha_find_null()

static HA_KEYSEG * ha_find_null ( HA_KEYSEG *  keyseg,
const uchar *  a 
)
static

◆ isam_key_length()

static uint isam_key_length ( MI_INFO *  info,
MI_KEYDEF *  keyinfo 
)
static

◆ lock_file()

int lock_file ( MI_CHECK *  param,
File  file,
int  lock_type,
const char *  filetype,
const char *  filename 
)

◆ mi_byte_checksum()

static ha_checksum mi_byte_checksum ( const uchar *  buf,
uint  length 
)
static

◆ mi_collect_stats_nonulls_first()

static void mi_collect_stats_nonulls_first ( HA_KEYSEG *  keyseg,
ulonglong *  notnull,
const uchar *  key 
)
static

◆ mi_collect_stats_nonulls_next()

static int mi_collect_stats_nonulls_next ( HA_KEYSEG *  keyseg,
ulonglong *  notnull,
uchar *  prev_key,
const uchar *  last_key 
)
static

◆ mi_disable_non_unique_index()

void mi_disable_non_unique_index ( MI_INFO *  info,
ha_rows  rows 
)

◆ mi_drop_all_indexes()

static int mi_drop_all_indexes ( MI_CHECK *  param,
MI_INFO *  info,
bool  force 
)
static

Drop all indexes.

Parameters
[in]paramcheck parameters
[in]infoMI_INFO handle
[in]forceif to force drop all indexes
Returns
status
Return values
0OK
!=0 Error
Note
Once allocated, index blocks remain part of the key file forever. When indexes are disabled, no block is freed. When enabling indexes, no block is freed either. The new indexes are create from new blocks. (Bug #4692)

Before recreating formerly disabled indexes, the unused blocks must be freed. There are two options to do this:

  • Follow the tree of disabled indexes, add all blocks to the deleted blocks chain. Would require a lot of random I/O.
  • Drop all blocks by clearing all index root pointers and all delete chain pointers and resetting key_file_length to the end of the index file header. This requires to recreate all indexes, even those that may still be intact. The second method is probably faster in most cases.

When disabling indexes, MySQL disables either all indexes or all non-unique indexes. When MySQL [re-]enables disabled indexes (T_CREATE_MISSING_KEYS), then we either have "lost" blocks in the index file, or there are no non-unique indexes. In the latter case, mi_repair*() would not be called as there would be no disabled indexes.

If there would be more unique indexes than disabled (non-unique) indexes, we could do the first method. But this is not implemented yet. By now we drop and recreate all indexes when repair is called.

However, there is an exception. Sometimes MySQL disables non-unique indexes when the table is empty (e.g. when copying a table in mysql_alter_table()). When enabling the non-unique indexes, they are still empty. So there is no index block that can be lost. This optimization is implemented in this function.

Note that in normal repair (T_CREATE_MISSING_KEYS not set) we recreate all enabled indexes unconditonally. We do not change the key_map. Otherwise we invert the key map temporarily (outside of this function) and recreate the then "seemingly" enabled indexes. When we cannot use the optimization, and drop all indexes, we pretend that all indexes were disabled. By the inversion, we will then recrate all indexes.

◆ mi_repair()

int mi_repair ( MI_CHECK *  param,
MI_INFO *  info,
char *  name,
int  rep_quick,
bool  no_copy_stat 
)

◆ mi_repair_by_sort()

int mi_repair_by_sort ( MI_CHECK *  param,
MI_INFO *  info,
const char *  name,
int  rep_quick,
bool  no_copy_stat 
)

◆ mi_sort_index()

int mi_sort_index ( MI_CHECK *  param,
MI_INFO *  info,
char *  name,
bool  no_copy_stat 
)

◆ mi_test_if_sort_rep()

bool mi_test_if_sort_rep ( MI_INFO *  info,
ha_rows  rows,
ulonglong  key_map,
bool  force 
)

◆ mi_too_big_key_for_sort()

static bool mi_too_big_key_for_sort ( MI_KEYDEF *  key,
ha_rows  rows 
)
static

◆ movepoint()

int movepoint ( MI_INFO *  info,
uchar *  record,
my_off_t  oldpos,
my_off_t  newpos,
uint  prot_key 
)

◆ myisamchk_init()

void myisamchk_init ( MI_CHECK *  param)

◆ recreate_table()

int recreate_table ( MI_CHECK *  param,
MI_INFO **  org_info,
char *  filename 
)

◆ set_data_file_type()

static void set_data_file_type ( SORT_INFO *  sort_info,
MYISAM_SHARE *  share 
)
static

◆ sort_delete_record()

static int sort_delete_record ( MI_SORT_PARAM *  sort_param)
static

◆ sort_ft_buf_flush()

int sort_ft_buf_flush ( MI_SORT_PARAM *  sort_param)

◆ sort_ft_key_read()

static int sort_ft_key_read ( MI_SORT_PARAM *  sort_param,
void *  key 
)
static

◆ sort_ft_key_write()

static int sort_ft_key_write ( MI_SORT_PARAM *  sort_param,
const void *  a 
)
static

◆ sort_get_next_record()

static int sort_get_next_record ( MI_SORT_PARAM *  sort_param)
static

◆ sort_insert_key()

static int sort_insert_key ( MI_SORT_PARAM *  sort_param,
SORT_KEY_BLOCKS *  key_block,
const uchar *  key,
my_off_t  prev_block 
)
static

◆ sort_key_cmp()

static int sort_key_cmp ( void *  cmp_arg,
unsigned char *  a,
unsigned char *  b 
)
static

◆ sort_key_read()

static int sort_key_read ( MI_SORT_PARAM *  sort_param,
void *  key 
)
static

◆ sort_key_write()

static int sort_key_write ( MI_SORT_PARAM *  sort_param,
const void *  a 
)
static

◆ sort_one_index()

static int sort_one_index ( MI_CHECK *  param,
MI_INFO *  info,
MI_KEYDEF *  keyinfo,
my_off_t  pagepos,
File  new_file 
)
static

◆ sort_write_record()

int sort_write_record ( MI_SORT_PARAM *  sort_param)

◆ test_if_almost_full()

int test_if_almost_full ( MI_INFO *  info)

◆ update_auto_increment_key()

void update_auto_increment_key ( MI_CHECK *  param,
MI_INFO *  info,
bool  repair_only 
)

◆ update_key_parts()

void update_key_parts ( MI_KEYDEF *  keyinfo,
ulong *  rec_per_key_part,
ulonglong *  unique,
ulonglong *  notnull,
ulonglong  records 
)

◆ update_state_info()

int update_state_info ( MI_CHECK *  param,
MI_INFO *  info,
uint  update 
)

◆ write_data_suffix()

int write_data_suffix ( SORT_INFO *  sort_info,
bool  fix_datafile 
)

◆ writekeys()

static int writekeys ( MI_SORT_PARAM *  sort_param)
static