42
42
#define XB_TMPFILE_SUFFIX ".tmp"
46
46
ulint from; /*!< range start */
47
47
ulint to; /*!< range end */
50
50
/* Cursor in a page map file */
51
struct page_map_cursor_t {
52
52
File fd; /*!< file descriptor */
53
53
IO_CACHE cache; /*!< IO_CACHE associated with fd */
56
/* Table descriptor for the index rebuild operation */
57
struct index_rebuild_table_t {
58
char* name; /* table name */
59
ulint space_id; /* space ID */
60
UT_LIST_NODE_T(index_rebuild_table_t) list; /* list node */
63
/* Thread descriptor for the index rebuild operation */
64
struct index_rebuild_thread_t {
65
ulint num; /* thread number */
66
pthread_t id; /* thread ID */
56
69
/* Empty page use to replace skipped pages in the data files */
57
70
static byte empty_page[UNIV_PAGE_SIZE_MAX];
60
73
sizeof(compacted_page_magic) - 1;
61
74
static const ulint compacted_page_magic_offset = FIL_PAGE_DATA;
76
/* Mutex protecting table_list */
77
static pthread_mutex_t table_list_mutex;
78
/* List of tablespaces to process by the index rebuild operation */
79
static UT_LIST_BASE_NODE_T(index_rebuild_table_t) table_list;
63
82
/************************************************************************
64
83
Compact page filter. */
65
84
static my_bool wf_compact_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
713
732
xb_rebuild_indexes_for_table(
714
/*=======================*/
715
dict_table_t* table, /*!< in: table */
716
trx_t* trx) /*!< in: transaction handle */
733
/*=========================*/
734
dict_table_t* table, /*!< in: table */
735
trx_t* trx, /*!< in: transaction handle */
736
ulint thread_n) /*!< in: thread number */
718
738
dict_index_t* index;
719
739
dict_index_t** indexes;
752
772
index = dict_table_get_first_index(table);
753
773
ut_a(dict_index_is_clust(index));
755
msg(" Dropping %lu index(es).\n", n_indexes);
775
row_mysql_lock_data_dictionary(trx);
757
777
for (i = 0; (index = dict_table_get_next_index(index)); i++) {
759
msg(" Found index %s\n", index->name);
779
msg("[%02lu] Found index %s\n", thread_n, index->name);
761
781
/* Pretend that it's the current trx that created this index.
762
782
Required to avoid 5.6+ debug assertions. */
805
825
row_merge_drop_indexes(trx, table, indexes, n_indexes);
808
msg(" Rebuilding %lu index(es).\n", n_indexes);
828
msg("[%02lu] Rebuilding %lu index(es).\n", thread_n, n_indexes);
810
830
error = row_merge_lock_table(trx, table, LOCK_X);
811
831
xb_a(error == DB_SUCCESS);
841
/* Commit trx to release latches on system tables */
842
trx_commit_for_mysql(trx);
843
trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
845
row_mysql_unlock_data_dictionary(trx);
847
/* Reacquire table lock for row_merge_build_indexes() */
848
error = row_merge_lock_table(trx, table, LOCK_X);
849
xb_a(error == DB_SUCCESS);
821
851
#if MYSQL_VERSION_ID >= 50600
822
852
error = row_merge_build_indexes(trx, table, table, FALSE, indexes,
823
853
add_key_nums, n_indexes, &dummy_table,
835
865
trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
868
/**************************************************************************
869
Worker thread function for index rebuild. */
872
xb_rebuild_indexes_thread_func(
873
/*===========================*/
874
void* arg) /* thread context */
877
index_rebuild_table_t* rebuild_table;
878
index_rebuild_thread_t* thread;
881
thread = (index_rebuild_thread_t *) arg;
883
trx = trx_allocate_for_mysql();
885
/* Suppress foreign key checks, as we are going to drop and recreate all
887
trx->check_foreigns = FALSE;
888
trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
890
/* Loop until there are no more tables in tables list */
892
pthread_mutex_lock(&table_list_mutex);
894
rebuild_table = UT_LIST_GET_FIRST(table_list);
896
if (rebuild_table == NULL) {
898
pthread_mutex_unlock(&table_list_mutex);
902
UT_LIST_REMOVE(list, table_list, rebuild_table);
904
pthread_mutex_unlock(&table_list_mutex);
906
ut_ad(rebuild_table->name);
907
ut_ad(!trx_sys_sys_space(rebuild_table->space_id));
909
row_mysql_lock_data_dictionary(trx);
911
table = dict_table_get_low(rebuild_table->name);
913
row_mysql_unlock_data_dictionary(trx);
916
ut_a(table->space == rebuild_table->space_id);
918
/* Discard change buffer entries for this space */
919
ibuf_delete_for_discarded_space(rebuild_table->space_id);
921
msg("[%02lu] Checking if there are indexes to rebuild in table "
922
"%s (space id: %lu)\n",
924
rebuild_table->name, rebuild_table->space_id);
926
xb_rebuild_indexes_for_table(table, trx, thread->num);
928
mem_free(rebuild_table->name);
929
mem_free(rebuild_table);
932
trx_commit_for_mysql(trx);
934
trx_free_for_mysql(trx);
838
939
/******************************************************************************
839
940
Rebuild all secondary indexes in all tables in separate spaces. Called from
840
941
innobase_start_or_create_for_mysql(). */
842
943
xb_compact_rebuild_indexes(void)
843
944
/*=============================*/
845
dict_table_t* sys_tables;
846
dict_index_t* sys_index;
946
dict_table_t* sys_tables;
947
dict_index_t* sys_index;
955
index_rebuild_table_t* rebuild_table;
956
index_rebuild_thread_t* threads;
857
959
#if MYSQL_VERSION_ID >= 50600
858
960
/* Set up the dummy table for the index rebuild error reporting */
860
962
dummy_table.s = &dummy_table_share;
863
/* Iterate all tables that are not in the system tablespace. */
965
/* Iterate all tables that are not in the system tablespace and add them
966
to the list of tables to be rebuilt later. */
865
968
trx = trx_allocate_for_mysql();
866
969
trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
868
/* Suppress foreign key checks, as we are going to drop and recreate all
870
trx->check_foreigns = FALSE;
872
971
row_mysql_lock_data_dictionary(trx);
874
973
/* Enlarge the fatal lock wait timeout during index rebuild
881
980
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
882
981
ut_a(!dict_table_is_comp(sys_tables));
983
pthread_mutex_init(&table_list_mutex, NULL);
984
UT_LIST_INIT(table_list);
884
986
xb_btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
912
1014
field = rec_get_nth_field_old(rec, 0, &len);
913
name = mem_strdupl((char*) field, len);
915
btr_pcur_store_position(&pcur, &mtr);
919
table = dict_table_get_low(name);
922
/* Discard change buffer entries for this space */
923
ibuf_delete_for_discarded_space(space_id);
925
msg("Rebuilding indexes for table %s (space id: %lu)\n", name,
928
xb_rebuild_indexes_for_table(table, trx);
934
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
1016
rebuild_table = static_cast<index_rebuild_table_t *>
1017
(mem_alloc(sizeof(*rebuild_table)));
1018
rebuild_table->name = mem_strdupl((char*) field, len);
1019
rebuild_table->space_id = space_id;
1021
UT_LIST_ADD_LAST(list, table_list, rebuild_table);
937
1024
btr_pcur_close(&pcur);
942
1029
trx_commit_for_mysql(trx);
944
1031
trx_free_for_mysql(trx);
1033
/* Start worker threads for the index rebuild operation */
1034
ut_ad(xtrabackup_rebuild_threads > 0);
1036
if (xtrabackup_rebuild_threads > 1) {
1037
msg("Starting %lu threads to rebuild indexes.\n",
1038
xtrabackup_rebuild_threads);
1041
threads = (index_rebuild_thread_t *)
1042
mem_alloc(sizeof(*threads) *
1043
xtrabackup_rebuild_threads);
1045
for (i = 0; i < xtrabackup_rebuild_threads; i++) {
1047
threads[i].num = i+1;
1048
if (pthread_create(&threads[i].id, NULL,
1049
xb_rebuild_indexes_thread_func,
1052
msg("error: pthread_create() failed: errno = %d\n",
1058
/* Wait for worker threads to finish */
1059
for (i = 0; i < xtrabackup_rebuild_threads; i++) {
1060
pthread_join(threads[i].id, NULL);