~hrvojem/percona-xtrabackup/rn-2.1.0-ga

« back to all changes in this revision

Viewing changes to src/compact.cc

  • Committer: Alexey Kopytov
  • Date: 2013-05-07 08:12:22 UTC
  • mfrom: (583.4.1 2.1)
  • Revision ID: akopytov@gmail.com-20130507081222-y1ne3vxo0eb1gkkx
MergedĀ lp:~akopytov/percona-xtrabackup/parallel-table-rebuild.

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
#define XB_TMPFILE_SUFFIX ".tmp"
43
43
 
44
44
/* Page range */
45
 
typedef struct {
 
45
struct page_range_t {
46
46
        ulint   from;                   /*!< range start */
47
47
        ulint   to;                     /*!< range end */
48
 
} page_range_t;
 
48
};
49
49
 
50
50
/* Cursor in a page map file */
51
 
typedef struct {
 
51
struct page_map_cursor_t {
52
52
        File            fd;     /*!< file descriptor */
53
53
        IO_CACHE        cache;  /*!< IO_CACHE associated with fd */
54
 
} page_map_cursor_t;
 
54
};
 
55
 
 
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 */
 
61
};
 
62
 
 
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 */
 
67
};
55
68
 
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;
62
75
 
 
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;
 
80
 
 
81
 
63
82
/************************************************************************
64
83
Compact page filter. */
65
84
static my_bool wf_compact_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
711
730
static
712
731
void
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 */
717
737
{
718
738
        dict_index_t*   index;
719
739
        dict_index_t**  indexes;
726
746
        ulint*          add_key_nums;
727
747
#endif
728
748
 
729
 
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
749
        ut_ad(!mutex_own(&(dict_sys->mutex)));
730
750
        ut_ad(table);
731
751
 
732
752
        ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
752
772
        index = dict_table_get_first_index(table);
753
773
        ut_a(dict_index_is_clust(index));
754
774
 
755
 
        msg("  Dropping %lu index(es).\n", n_indexes);
 
775
        row_mysql_lock_data_dictionary(trx);
756
776
 
757
777
        for (i = 0; (index = dict_table_get_next_index(index)); i++) {
758
778
 
759
 
                msg("  Found index %s\n", index->name);
 
779
                msg("[%02lu]   Found index %s\n", thread_n, index->name);
760
780
 
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);
806
826
#endif
807
827
 
808
 
        msg("  Rebuilding %lu index(es).\n", n_indexes);
 
828
        msg("[%02lu]   Rebuilding %lu index(es).\n", thread_n, n_indexes);
809
829
 
810
830
        error = row_merge_lock_table(trx, table, LOCK_X);
811
831
        xb_a(error == DB_SUCCESS);
818
838
#endif
819
839
        }
820
840
 
 
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);
 
844
 
 
845
        row_mysql_unlock_data_dictionary(trx);
 
846
 
 
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);
 
850
 
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);
836
866
}
837
867
 
 
868
/**************************************************************************
 
869
Worker thread function for index rebuild. */
 
870
static
 
871
void *
 
872
xb_rebuild_indexes_thread_func(
 
873
/*===========================*/
 
874
        void*   arg)    /* thread context */
 
875
{
 
876
        dict_table_t*           table;
 
877
        index_rebuild_table_t*  rebuild_table;
 
878
        index_rebuild_thread_t* thread;
 
879
        trx_t*                  trx;
 
880
 
 
881
        thread = (index_rebuild_thread_t *) arg;
 
882
 
 
883
        trx = trx_allocate_for_mysql();
 
884
 
 
885
        /* Suppress foreign key checks, as we are going to drop and recreate all
 
886
        secondary keys. */
 
887
        trx->check_foreigns = FALSE;
 
888
        trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
 
889
 
 
890
        /* Loop until there are no more tables in tables list */
 
891
        for (;;) {
 
892
                pthread_mutex_lock(&table_list_mutex);
 
893
 
 
894
                rebuild_table = UT_LIST_GET_FIRST(table_list);
 
895
 
 
896
                if (rebuild_table == NULL) {
 
897
 
 
898
                        pthread_mutex_unlock(&table_list_mutex);
 
899
                        break;
 
900
                }
 
901
 
 
902
                UT_LIST_REMOVE(list, table_list, rebuild_table);
 
903
 
 
904
                pthread_mutex_unlock(&table_list_mutex);
 
905
 
 
906
                ut_ad(rebuild_table->name);
 
907
                ut_ad(!trx_sys_sys_space(rebuild_table->space_id));
 
908
 
 
909
                row_mysql_lock_data_dictionary(trx);
 
910
 
 
911
                table = dict_table_get_low(rebuild_table->name);
 
912
 
 
913
                row_mysql_unlock_data_dictionary(trx);
 
914
 
 
915
                ut_a(table != NULL);
 
916
                ut_a(table->space == rebuild_table->space_id);
 
917
 
 
918
                /* Discard change buffer entries for this space */
 
919
                ibuf_delete_for_discarded_space(rebuild_table->space_id);
 
920
 
 
921
                msg("[%02lu] Checking if there are indexes to rebuild in table "
 
922
                    "%s (space id: %lu)\n",
 
923
                    thread->num,
 
924
                    rebuild_table->name, rebuild_table->space_id);
 
925
 
 
926
                xb_rebuild_indexes_for_table(table, trx, thread->num);
 
927
 
 
928
                mem_free(rebuild_table->name);
 
929
                mem_free(rebuild_table);
 
930
        }
 
931
 
 
932
        trx_commit_for_mysql(trx);
 
933
 
 
934
        trx_free_for_mysql(trx);
 
935
 
 
936
        return(NULL);
 
937
}
 
938
 
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
/*=============================*/
844
945
{
845
 
        dict_table_t*   sys_tables;
846
 
        dict_index_t*   sys_index;
847
 
        btr_pcur_t      pcur;
848
 
        const rec_t*    rec;
849
 
        mtr_t           mtr;
850
 
        const byte*     field;
851
 
        ulint           len;
852
 
        ulint           space_id;
853
 
        char*           name;
854
 
        dict_table_t*   table;
855
 
        trx_t*          trx;
 
946
        dict_table_t*           sys_tables;
 
947
        dict_index_t*           sys_index;
 
948
        btr_pcur_t              pcur;
 
949
        const rec_t*            rec;
 
950
        mtr_t                   mtr;
 
951
        const byte*             field;
 
952
        ulint                   len;
 
953
        ulint                   space_id;
 
954
        trx_t*                  trx;
 
955
        index_rebuild_table_t*  rebuild_table;
 
956
        index_rebuild_thread_t* threads;
 
957
        ulint                   i;
856
958
 
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;
861
963
#endif
862
964
 
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. */
864
967
 
865
968
        trx = trx_allocate_for_mysql();
866
969
        trx_start_for_ddl(trx, TRX_DICT_OP_INDEX);
867
970
 
868
 
        /* Suppress foreign key checks, as we are going to drop and recreate all
869
 
        secondary keys. */
870
 
        trx->check_foreigns = FALSE;
871
 
 
872
971
        row_mysql_lock_data_dictionary(trx);
873
972
 
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));
883
982
 
 
983
        pthread_mutex_init(&table_list_mutex, NULL);
 
984
        UT_LIST_INIT(table_list);
 
985
 
884
986
        xb_btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
885
987
                                       TRUE, 0, &mtr);
886
988
        for (;;) {
910
1012
                }
911
1013
 
912
1014
                field = rec_get_nth_field_old(rec, 0, &len);
913
 
                name = mem_strdupl((char*) field, len);
914
 
 
915
 
                btr_pcur_store_position(&pcur, &mtr);
916
 
 
917
 
                mtr_commit(&mtr);
918
 
 
919
 
                table = dict_table_get_low(name);
920
 
                ut_a(table != NULL);
921
 
 
922
 
                /* Discard change buffer entries for this space */
923
 
                ibuf_delete_for_discarded_space(space_id);
924
 
 
925
 
                msg("Rebuilding indexes for table %s (space id: %lu)\n", name,
926
 
                    space_id);
927
 
 
928
 
                xb_rebuild_indexes_for_table(table, trx);
929
 
 
930
 
                mem_free(name);
931
 
 
932
 
                mtr_start(&mtr);
933
 
 
934
 
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
 
1015
 
 
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;
 
1020
 
 
1021
                UT_LIST_ADD_LAST(list, table_list, rebuild_table);
935
1022
        }
936
1023
 
937
1024
        btr_pcur_close(&pcur);
942
1029
        trx_commit_for_mysql(trx);
943
1030
 
944
1031
        trx_free_for_mysql(trx);
 
1032
 
 
1033
        /* Start worker threads for the index rebuild operation */
 
1034
        ut_ad(xtrabackup_rebuild_threads > 0);
 
1035
 
 
1036
        if (xtrabackup_rebuild_threads > 1) {
 
1037
                msg("Starting %lu threads to rebuild indexes.\n",
 
1038
                    xtrabackup_rebuild_threads);
 
1039
        }
 
1040
 
 
1041
        threads = (index_rebuild_thread_t *)
 
1042
                mem_alloc(sizeof(*threads) *
 
1043
                          xtrabackup_rebuild_threads);
 
1044
 
 
1045
        for (i = 0; i < xtrabackup_rebuild_threads; i++) {
 
1046
 
 
1047
                threads[i].num = i+1;
 
1048
                if (pthread_create(&threads[i].id, NULL,
 
1049
                                   xb_rebuild_indexes_thread_func,
 
1050
                                   &threads[i])) {
 
1051
 
 
1052
                        msg("error: pthread_create() failed: errno = %d\n",
 
1053
                            errno);
 
1054
                        ut_a(0);
 
1055
                }
 
1056
        }
 
1057
 
 
1058
        /* Wait for worker threads to finish */
 
1059
        for (i = 0; i < xtrabackup_rebuild_threads; i++) {
 
1060
                pthread_join(threads[i].id, NULL);
 
1061
        }
 
1062
 
 
1063
        mem_free(threads);
945
1064
}