Merge lp:~sergei.glushchenko/percona-xtrabackup/xb20-bug932623 into lp:percona-xtrabackup/2.0
- xb20-bug932623
- Merge into 2.0
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Alexey Kopytov | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 452 | ||||
Proposed branch: | lp:~sergei.glushchenko/percona-xtrabackup/xb20-bug932623 | ||||
Merge into: | lp:percona-xtrabackup/2.0 | ||||
Diff against target: |
904 lines (+582/-113) 3 files modified
patches/innodb51_builtin.patch (+67/-4) src/xtrabackup.c (+430/-109) test/t/bug932623.sh (+85/-0) |
||||
To merge this branch: | bzr merge lp:~sergei.glushchenko/percona-xtrabackup/xb20-bug932623 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
Review via email: mp+113690@code.launchpad.net |
Commit message
Description of the change
Bug #932623: RENAME TABLE causes incremental prepare to fail
Fixed by applying .delta changes to tablespace with matching ID.
Matching tablespace also renamed to match .delta name.
When tablespace with matching name but different ID exists in full
backup, it renamed to tmp#ID.ibd. When no matching tablespace found,
new one created.
http://
#24669
Alexey Kopytov (akopytov) wrote : | # |
Forgot to mention that the following code can be simplified:
14 if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
15 r= FALSE;
16 + if (!r || fscanf(fp, "space_id = %lu\n", &info->space_id) != 1)
17 + r= FALSE;
and
31 snprintf(buf, sizeof(buf), "page_size = %lu\n", info->page_size);
32 -
33 len = strlen(buf);
34 +
35 + snprintf(buf + len, sizeof(buf) - len, "space_id = %lu\n", info->space_id);
36 + len += strlen(buf + len);
37 +
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
It was really tricky to initialize fil_system, especially for built-in InnoDB and for debug builds.
Jenkins build:
http://
Alexey Kopytov (akopytov) wrote : | # |
Sergei,
Can you explain the problems with initializing fil_system (including the ones in built-in InnoDB) and how you solved them?
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Alexey,
1. fil_space_get_by_id and fil_space_
2. fil_space use hash tables, which are not working without calling mem_init on debug builds.
3. When we are applying deltas we initialize some parts of InnoDB, then releasing and closing them, and then initializing them and some other parts again. The problem with built-it InnoDB is that it doesn't have proper functions to uninitialize fil, mem, and sync. Plugin have some tricks to do it properly (for example we should close sync, which frees all muteness, then close fil, which checks that sync is closed and only after that been done, we close men. But when closing men it use men_hash_mutex, which wasn't closed in sync_close by using special hack). In case of xtrabackup I cheated and not freed mem in many *_close functions, because it will be freed when ut_free_all_mem called.
4. io_handler_thread had an infinite loop:
for (i = 0;; i++) {
fil_aio_
}
and there was no way to finish this thread. I inserted check of srv_shutdown_state.
for (i = 0; srv_shutdown_state != SRV_SHUTDOWN_
fil_
}
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Spellchecker did bad thing by replacing s/mem/men/ :)
Alexey Kopytov (akopytov) wrote : | # |
Sergei,
Thanks for clarifications. My comments on the new version of the fix:
- I wonder if it would be less invasive to define our own simple
wrappers around "HASH_SEARCH(hash, fil_system->spaces, id, space,
space->id == id);" so we don't have to patch InnoDB or provide our
own implementations for built-in InnoDB, and mess with
mutexes. I.e. can we have xb_space_
- the code in xtrabackup's version of io_handler_thread() doesn't use
the 'i' variable, why not just copy the code from InnoDB, i.e.:
while (srv_shutdown_state != SRV_SHUTDOWN_
fil_aio_
}
- fil_free_
is not used anywhere?
- in fact, ut_free_all_mem() will not free anything when the system
malloc() is used instead of the InnoDB own malloc manager, i.e. when
srv_
thoughts on how to fix that, but I suggest we'll do it later as a
part of bigger refactoring.
- POSIX guarantees the result of snprintf() to be always
zero-
+ snprintf(dest_dir, FN_REFLEN, "%s/%s",
+ xtrabackup_
+ dest_dir[FN_REFLEN - 1] = 0;
if you care about Windows, you should be using either my_snprintf()
or ut_snprintf(), which do the right thing on Windows. But
currently, xtrabackup.c just uses snprintf() in other places anyway,
so what's the point to do some windows-specific stuff in this
patch. We can do s/snprintf/
have to support Windows.
- this code just uses sprintf() instead snprintf() for some reasons:
+ sprintf(tmpname, "./%s/tmp#%lu", dbname, fil_space->id);
- I think the output in xb_delta_
verbose. Let's only print messages when something unexpected
happens, i.e. remove these messages:
+ msg("xtrabackup: Looking for tablespace %s with id %lu by name\n",
+ dest_space_name, space_id);
and
+ msg("xtrabackup: Looking for tablespace %s with id %lu by id\n",
+ dest_space_name, space_id);
and
+ msg("xtrabackup: Found matching tablespace %s\n",
+ fil_space->name);
and
+ msg("xtrabackup: Created tablespace %s with id %lu.\n",
+ dest_space_name, space_id);
- what's the point to rename a tablespace with the same name but a
different ID to tmp#id? the only case when it happens is when a
tablespace was recreated between the full backup and an incremental
one. In which case, if we rename the dropped table, we will end up
with ghost 'tmp...' table in the full backup.
- this if() block can be merged:
+ if (xtrabackup_
+ err = xb_data_
+ if (err != DB_SUCCESS) {
+ msg("xtrabackup: error: xb_data_
+ "error code %lu\n", err);
+ goto error;
+ }
+
+ if(!xtrabackup_
+ xb_data_
+ goto error;
+ }
+ }
+
+ if (xtrabackup_
+ xb_data_
+ }
- can we also a add a cross-db rename test to bug932623.sh?
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Alexey,
> - I wonder if it would be less invasive to define our own simple
> wrappers around "HASH_SEARCH(hash, fil_system->spaces, id, space,
> space->id == id);" so we don't have to patch InnoDB or provide our
> own implementations for built-in InnoDB, and mess with
> mutexes. I.e. can we have xb_space_
I've wrote xb_space_by_* wrappers. The only modification of innodb51_
>
> - the code in xtrabackup's version of io_handler_thread() doesn't use
> the 'i' variable, why not just copy the code from InnoDB, i.e.:
>
> while (srv_shutdown_state != SRV_SHUTDOWN_
> fil_aio_
> }
>
fixed
> - fil_free_
> is not used anywhere?
>
Yes. I forgot to put call in proper place, fixed.
> - in fact, ut_free_all_mem() will not free anything when the system
> malloc() is used instead of the InnoDB own malloc manager, i.e. when
> srv_use_sys_malloc == TRUE, which is the default. I have some
> thoughts on how to fix that, but I suggest we'll do it later as a
> part of bigger refactoring.
>
OK. Hopefully memory leaks will not be critical.
> - POSIX guarantees the result of snprintf() to be always
> zero-terminated, so there's no need for things like:
>
> + snprintf(dest_dir, FN_REFLEN, "%s/%s",
> + xtrabackup_
> + dest_dir[FN_REFLEN - 1] = 0;
>
> if you care about Windows, you should be using either my_snprintf()
> or ut_snprintf(), which do the right thing on Windows. But
> currently, xtrabackup.c just uses snprintf() in other places anyway,
> so what's the point to do some windows-specific stuff in this
> patch. We can do s/snprintf/
> have to support Windows.
>
Great! I removed implicit zero-terminating statement.
> - this code just uses sprintf() instead snprintf() for some reasons:
>
> + sprintf(tmpname, "./%s/tmp#%lu", dbname,
> fil_space->id);
>
Hmm... I expected that generated tmpname cannot be longer than FN_REFLEN. I've changed to snprintf for more safety.
> - I think the output in xb_delta_
> verbose. Let's only print messages when something unexpected
> happens, i.e. remove these messages:
>
> + msg("xtrabackup: Looking for tablespace %s with id %lu by name\n",
> + dest_space_name, space_id);
>
> and
>
> + msg("xtrabackup: Looking for tablespace %s with id %lu by id\n",
> + dest_space_name, space_id);
>
> and
>
> + msg("xtrabackup: Found matching tablespace %s\n",
> + fil_space->name);
>
> and
>
> + msg("xtrabackup: Created tablespace %s with id %lu.\n",
> + dest_space_name, space_id);
>
Removed.
>
> - what's the point to rename a tablespace with the same name but a
> different ID to tmp#id? the only case when it happens is when a
> tablespace was recreated between the full backup and an incremental
> one....
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Alexey Kopytov (akopytov) wrote : | # |
Approved. Please when merging the fix to 2.1 move xb_space_get_by_*() and fil_free_
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
This patch regresses on compressed tablespace creation: the "flags" arg for the fil_space_create() is *not* zip_size. Please do not resubmit this MP. I have follow-up MPs depending on the code and "Approved" status of this one and I will fix this in a follow-up right now.
Preview Diff
1 | === modified file 'patches/innodb51_builtin.patch' | |||
2 | --- patches/innodb51_builtin.patch 2012-02-10 05:04:04 +0000 | |||
3 | +++ patches/innodb51_builtin.patch 2012-07-18 15:36:21 +0000 | |||
4 | @@ -613,7 +613,21 @@ | |||
5 | 613 | 613 | ||
6 | 614 | --- a/storage/innobase/include/mem0mem.h | 614 | --- a/storage/innobase/include/mem0mem.h |
7 | 615 | +++ b/storage/innobase/include/mem0mem.h | 615 | +++ b/storage/innobase/include/mem0mem.h |
9 | 616 | @@ -401,6 +401,7 @@ | 616 | @@ -63,6 +63,13 @@ |
10 | 617 | mem_init( | ||
11 | 618 | /*=====*/ | ||
12 | 619 | ulint size); /* in: common pool size in bytes */ | ||
13 | 620 | + | ||
14 | 621 | +/******************************************************************//** | ||
15 | 622 | +Closes the memory system. */ | ||
16 | 623 | +void | ||
17 | 624 | +mem_close(void); | ||
18 | 625 | +/*===========*/ | ||
19 | 626 | + | ||
20 | 627 | /****************************************************************** | ||
21 | 628 | Use this macro instead of the corresponding function! Macro for memory | ||
22 | 629 | heap creation. */ | ||
23 | 630 | @@ -401,6 +409,7 @@ | ||
24 | 617 | allocated buffer frame, which can be appended as a | 631 | allocated buffer frame, which can be appended as a |
25 | 618 | free block to the heap, if we need more space; | 632 | free block to the heap, if we need more space; |
26 | 619 | otherwise, this is NULL */ | 633 | otherwise, this is NULL */ |
27 | @@ -654,6 +668,21 @@ | |||
28 | 654 | 668 | ||
29 | 655 | if (heap->free_block) { | 669 | if (heap->free_block) { |
30 | 656 | size += UNIV_PAGE_SIZE; | 670 | size += UNIV_PAGE_SIZE; |
31 | 671 | --- a/storage/innobase/include/mem0pool.h | ||
32 | 672 | +++ b/storage/innobase/include/mem0pool.h | ||
33 | 673 | @@ -42,6 +42,12 @@ | ||
34 | 674 | /*============*/ | ||
35 | 675 | /* out: memory pool */ | ||
36 | 676 | ulint size); /* in: pool size in bytes */ | ||
37 | 677 | +/********************************************************************//** | ||
38 | 678 | +Frees a memory pool. */ | ||
39 | 679 | +void | ||
40 | 680 | +mem_pool_free( | ||
41 | 681 | +/*==========*/ | ||
42 | 682 | + mem_pool_t* pool); /*!< in, own: memory pool */ | ||
43 | 683 | /************************************************************************ | ||
44 | 684 | Allocates memory from a pool. NOTE: This low-level function should only be | ||
45 | 685 | used in mem0mem.*! */ | ||
46 | 657 | --- a/storage/innobase/include/srv0srv.h | 686 | --- a/storage/innobase/include/srv0srv.h |
47 | 658 | +++ b/storage/innobase/include/srv0srv.h | 687 | +++ b/storage/innobase/include/srv0srv.h |
48 | 659 | @@ -60,6 +60,8 @@ | 688 | @@ -60,6 +60,8 @@ |
49 | @@ -958,7 +987,7 @@ | |||
50 | 958 | /********************************************************** | 987 | /********************************************************** |
51 | 959 | --- a/storage/innobase/mem/mem0dbg.c | 988 | --- a/storage/innobase/mem/mem0dbg.c |
52 | 960 | +++ b/storage/innobase/mem/mem0dbg.c | 989 | +++ b/storage/innobase/mem/mem0dbg.c |
54 | 961 | @@ -133,6 +133,14 @@ | 990 | @@ -133,9 +133,30 @@ |
55 | 962 | mem_hash_initialized = TRUE; | 991 | mem_hash_initialized = TRUE; |
56 | 963 | #endif | 992 | #endif |
57 | 964 | 993 | ||
58 | @@ -973,6 +1002,22 @@ | |||
59 | 973 | mem_comm_pool = mem_pool_create(size); | 1002 | mem_comm_pool = mem_pool_create(size); |
60 | 974 | } | 1003 | } |
61 | 975 | 1004 | ||
62 | 1005 | +/******************************************************************//** | ||
63 | 1006 | +Closes the memory system. */ | ||
64 | 1007 | +void | ||
65 | 1008 | +mem_close(void) | ||
66 | 1009 | +/*===========*/ | ||
67 | 1010 | +{ | ||
68 | 1011 | + mem_pool_free(mem_comm_pool); | ||
69 | 1012 | + mem_comm_pool = NULL; | ||
70 | 1013 | +#ifdef UNIV_MEM_DEBUG | ||
71 | 1014 | + mem_hash_initialized = FALSE; | ||
72 | 1015 | +#endif /* UNIV_MEM_DEBUG */ | ||
73 | 1016 | +} | ||
74 | 1017 | + | ||
75 | 1018 | #ifdef UNIV_MEM_DEBUG | ||
76 | 1019 | /********************************************************************** | ||
77 | 1020 | Initializes an allocated memory field in the debug version. */ | ||
78 | 976 | --- a/storage/innobase/mem/mem0mem.c | 1021 | --- a/storage/innobase/mem/mem0mem.c |
79 | 977 | +++ b/storage/innobase/mem/mem0mem.c | 1022 | +++ b/storage/innobase/mem/mem0mem.c |
80 | 978 | @@ -472,6 +472,7 @@ | 1023 | @@ -472,6 +472,7 @@ |
81 | @@ -1026,7 +1071,25 @@ | |||
82 | 1026 | pool = ut_malloc(sizeof(mem_pool_t)); | 1071 | pool = ut_malloc(sizeof(mem_pool_t)); |
83 | 1027 | 1072 | ||
84 | 1028 | /* We do not set the memory to zero (FALSE) in the pool, | 1073 | /* We do not set the memory to zero (FALSE) in the pool, |
86 | 1029 | @@ -333,6 +332,10 @@ | 1074 | @@ -244,6 +243,17 @@ |
87 | 1075 | return(pool); | ||
88 | 1076 | } | ||
89 | 1077 | |||
90 | 1078 | +/********************************************************************//** | ||
91 | 1079 | +Frees a memory pool. */ | ||
92 | 1080 | +void | ||
93 | 1081 | +mem_pool_free( | ||
94 | 1082 | +/*==========*/ | ||
95 | 1083 | + mem_pool_t* pool) /*!< in, own: memory pool */ | ||
96 | 1084 | +{ | ||
97 | 1085 | + ut_free(pool->buf); | ||
98 | 1086 | + ut_free(pool); | ||
99 | 1087 | +} | ||
100 | 1088 | + | ||
101 | 1089 | /************************************************************************ | ||
102 | 1090 | Fills the specified free list. */ | ||
103 | 1091 | static | ||
104 | 1092 | @@ -333,6 +344,10 @@ | ||
105 | 1030 | ulint n; | 1093 | ulint n; |
106 | 1031 | ibool ret; | 1094 | ibool ret; |
107 | 1032 | 1095 | ||
108 | @@ -1037,7 +1100,7 @@ | |||
109 | 1037 | n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); | 1100 | n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); |
110 | 1038 | 1101 | ||
111 | 1039 | mutex_enter(&(pool->mutex)); | 1102 | mutex_enter(&(pool->mutex)); |
113 | 1040 | @@ -465,6 +468,11 @@ | 1103 | @@ -465,6 +480,11 @@ |
114 | 1041 | ulint size; | 1104 | ulint size; |
115 | 1042 | ulint n; | 1105 | ulint n; |
116 | 1043 | 1106 | ||
117 | 1044 | 1107 | ||
118 | === modified file 'src/xtrabackup.c' | |||
119 | --- src/xtrabackup.c 2012-06-20 07:36:26 +0000 | |||
120 | +++ src/xtrabackup.c 2012-07-18 15:36:21 +0000 | |||
121 | @@ -655,10 +655,107 @@ | |||
122 | 655 | 655 | ||
123 | 656 | typedef struct { | 656 | typedef struct { |
124 | 657 | ulint page_size; | 657 | ulint page_size; |
125 | 658 | ulint space_id; | ||
126 | 658 | } xb_delta_info_t; | 659 | } xb_delta_info_t; |
127 | 659 | 660 | ||
128 | 660 | extern fil_system_t* fil_system; | 661 | extern fil_system_t* fil_system; |
129 | 661 | 662 | ||
130 | 663 | /** Value of fil_space_struct::magic_n */ | ||
131 | 664 | #define FIL_SPACE_MAGIC_N 89472 | ||
132 | 665 | |||
133 | 666 | /*******************************************************************//** | ||
134 | 667 | Returns the table space by a given id, NULL if not found. */ | ||
135 | 668 | fil_space_t* | ||
136 | 669 | xb_space_get_by_id( | ||
137 | 670 | /*================*/ | ||
138 | 671 | ulint id); /*!< in: space id */ | ||
139 | 672 | |||
140 | 673 | /*******************************************************************//** | ||
141 | 674 | Returns the table space by a given name, NULL if not found. */ | ||
142 | 675 | fil_space_t* | ||
143 | 676 | xb_space_get_by_name( | ||
144 | 677 | /*==================*/ | ||
145 | 678 | const char* name); /*!< in: space name */ | ||
146 | 679 | |||
147 | 680 | /*******************************************************************//** | ||
148 | 681 | Returns the table space by a given id, NULL if not found. */ | ||
149 | 682 | fil_space_t* | ||
150 | 683 | xb_space_get_by_id( | ||
151 | 684 | /*================*/ | ||
152 | 685 | ulint id) /*!< in: space id */ | ||
153 | 686 | { | ||
154 | 687 | fil_space_t* space; | ||
155 | 688 | |||
156 | 689 | ut_ad(mutex_own(&fil_system->mutex)); | ||
157 | 690 | |||
158 | 691 | #ifdef INNODB_VERSION_SHORT | ||
159 | 692 | HASH_SEARCH(hash, fil_system->spaces, id, | ||
160 | 693 | fil_space_t*, space, | ||
161 | 694 | ut_ad(space->magic_n == FIL_SPACE_MAGIC_N), | ||
162 | 695 | space->id == id); | ||
163 | 696 | #else | ||
164 | 697 | HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id); | ||
165 | 698 | #endif | ||
166 | 699 | |||
167 | 700 | return(space); | ||
168 | 701 | } | ||
169 | 702 | |||
170 | 703 | /*******************************************************************//** | ||
171 | 704 | Returns the table space by a given name, NULL if not found. */ | ||
172 | 705 | fil_space_t* | ||
173 | 706 | xb_space_get_by_name( | ||
174 | 707 | /*==================*/ | ||
175 | 708 | const char* name) /*!< in: space name */ | ||
176 | 709 | { | ||
177 | 710 | fil_space_t* space; | ||
178 | 711 | ulint fold; | ||
179 | 712 | |||
180 | 713 | ut_ad(mutex_own(&fil_system->mutex)); | ||
181 | 714 | |||
182 | 715 | #ifdef INNODB_VERSION_SHORT | ||
183 | 716 | fold = ut_fold_string(name); | ||
184 | 717 | HASH_SEARCH(name_hash, fil_system->name_hash, fold, | ||
185 | 718 | fil_space_t*, space, | ||
186 | 719 | ut_ad(space->magic_n == FIL_SPACE_MAGIC_N), | ||
187 | 720 | !strcmp(name, space->name)); | ||
188 | 721 | #else | ||
189 | 722 | HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name), | ||
190 | 723 | space, 0 == strcmp(name, space->name)); | ||
191 | 724 | #endif | ||
192 | 725 | |||
193 | 726 | return(space); | ||
194 | 727 | } | ||
195 | 728 | |||
196 | 729 | #ifndef INNODB_VERSION_SHORT | ||
197 | 730 | |||
198 | 731 | /*******************************************************************//** | ||
199 | 732 | Free all spaces in space_list. */ | ||
200 | 733 | void | ||
201 | 734 | fil_free_all_spaces(void) | ||
202 | 735 | /*=====================*/ | ||
203 | 736 | { | ||
204 | 737 | fil_space_t* space; | ||
205 | 738 | |||
206 | 739 | mutex_enter(&fil_system->mutex); | ||
207 | 740 | |||
208 | 741 | space = UT_LIST_GET_FIRST(fil_system->space_list); | ||
209 | 742 | |||
210 | 743 | while (space != NULL) { | ||
211 | 744 | fil_node_t* node; | ||
212 | 745 | fil_space_t* prev_space = space; | ||
213 | 746 | |||
214 | 747 | space = UT_LIST_GET_NEXT(space_list, space); | ||
215 | 748 | |||
216 | 749 | fil_space_free(prev_space->id, FALSE); | ||
217 | 750 | } | ||
218 | 751 | |||
219 | 752 | mutex_exit(&fil_system->mutex); | ||
220 | 753 | } | ||
221 | 754 | |||
222 | 755 | #define SRV_SHUTDOWN_NONE 0 | ||
223 | 756 | |||
224 | 757 | #endif | ||
225 | 758 | |||
226 | 662 | /* ==end=== definition at fil0fil.c === */ | 759 | /* ==end=== definition at fil0fil.c === */ |
227 | 663 | 760 | ||
228 | 664 | 761 | ||
229 | @@ -2752,7 +2849,8 @@ | |||
230 | 2752 | return(TRUE); | 2849 | return(TRUE); |
231 | 2753 | } | 2850 | } |
232 | 2754 | 2851 | ||
234 | 2755 | if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1) | 2852 | if (fscanf(fp, "page_size = %lu\nspace_id = %lu\n", |
235 | 2853 | &info->page_size, &info->space_id) != 2) | ||
236 | 2756 | r= FALSE; | 2854 | r= FALSE; |
237 | 2757 | 2855 | ||
238 | 2758 | fclose(fp); | 2856 | fclose(fp); |
239 | @@ -2770,14 +2868,16 @@ | |||
240 | 2770 | { | 2868 | { |
241 | 2771 | datasink_t *ds = ds_ctxt->datasink; | 2869 | datasink_t *ds = ds_ctxt->datasink; |
242 | 2772 | ds_file_t *f; | 2870 | ds_file_t *f; |
244 | 2773 | char buf[32]; | 2871 | char buf[64]; |
245 | 2774 | my_bool ret; | 2872 | my_bool ret; |
246 | 2775 | size_t len; | 2873 | size_t len; |
247 | 2776 | MY_STAT mystat; | 2874 | MY_STAT mystat; |
248 | 2777 | 2875 | ||
251 | 2778 | snprintf(buf, sizeof(buf), "page_size = %lu\n", info->page_size); | 2876 | snprintf(buf, sizeof(buf), |
252 | 2779 | 2877 | "page_size = %lu\nspace_id = %lu\n", | |
253 | 2878 | info->page_size, info->space_id); | ||
254 | 2780 | len = strlen(buf); | 2879 | len = strlen(buf); |
255 | 2880 | |||
256 | 2781 | mystat.st_size = len; | 2881 | mystat.st_size = len; |
257 | 2782 | mystat.st_mtime = my_time(0); | 2882 | mystat.st_mtime = my_time(0); |
258 | 2783 | 2883 | ||
259 | @@ -2981,6 +3081,7 @@ | |||
260 | 2981 | ds_file_t *dstfile = NULL; | 3081 | ds_file_t *dstfile = NULL; |
261 | 2982 | 3082 | ||
262 | 2983 | info.page_size = 0; | 3083 | info.page_size = 0; |
263 | 3084 | info.space_id = 0; | ||
264 | 2984 | 3085 | ||
265 | 2985 | #ifdef XTRADB_BASED | 3086 | #ifdef XTRADB_BASED |
266 | 2986 | if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id))) | 3087 | if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id))) |
267 | @@ -3163,6 +3264,7 @@ | |||
268 | 3163 | page_in_buffer++; | 3264 | page_in_buffer++; |
269 | 3164 | 3265 | ||
270 | 3165 | info.page_size = page_size; | 3266 | info.page_size = page_size; |
271 | 3267 | info.space_id = node->space->id; | ||
272 | 3166 | } else | 3268 | } else |
273 | 3167 | info.page_size = 0; | 3269 | info.page_size = 0; |
274 | 3168 | 3270 | ||
275 | @@ -3722,11 +3824,10 @@ | |||
276 | 3722 | void* arg) | 3824 | void* arg) |
277 | 3723 | { | 3825 | { |
278 | 3724 | ulint segment; | 3826 | ulint segment; |
279 | 3725 | ulint i; | ||
280 | 3726 | 3827 | ||
281 | 3727 | segment = *((ulint*)arg); | 3828 | segment = *((ulint*)arg); |
282 | 3728 | 3829 | ||
284 | 3729 | for (i = 0;; i++) { | 3830 | while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) { |
285 | 3730 | fil_aio_wait(segment); | 3831 | fil_aio_wait(segment); |
286 | 3731 | } | 3832 | } |
287 | 3732 | 3833 | ||
288 | @@ -3744,6 +3845,141 @@ | |||
289 | 3744 | #endif | 3845 | #endif |
290 | 3745 | } | 3846 | } |
291 | 3746 | 3847 | ||
292 | 3848 | #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD | ||
293 | 3849 | #define SRV_MAX_N_PENDING_SYNC_IOS 100 | ||
294 | 3850 | |||
295 | 3851 | /************************************************************************ | ||
296 | 3852 | Initialize the tablespace memory cache and populate it by scanning for and | ||
297 | 3853 | opening data files. | ||
298 | 3854 | @returns DB_SUCCESS or error code.*/ | ||
299 | 3855 | ulint | ||
300 | 3856 | xb_data_files_init(void) | ||
301 | 3857 | /*====================*/ | ||
302 | 3858 | { | ||
303 | 3859 | ulint i; | ||
304 | 3860 | ibool create_new_db; | ||
305 | 3861 | #ifdef XTRADB_BASED | ||
306 | 3862 | ibool create_new_doublewrite_file; | ||
307 | 3863 | #endif | ||
308 | 3864 | ulint err; | ||
309 | 3865 | LSN64 min_flushed_lsn; | ||
310 | 3866 | LSN64 max_flushed_lsn; | ||
311 | 3867 | ulint sum_of_new_sizes; | ||
312 | 3868 | |||
313 | 3869 | #ifndef INNODB_VERSION_SHORT | ||
314 | 3870 | os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD | ||
315 | 3871 | * srv_n_file_io_threads, | ||
316 | 3872 | srv_n_file_io_threads, | ||
317 | 3873 | SRV_MAX_N_PENDING_SYNC_IOS); | ||
318 | 3874 | |||
319 | 3875 | fil_init(srv_max_n_open_files); | ||
320 | 3876 | #else | ||
321 | 3877 | srv_n_file_io_threads = 2 + srv_n_read_io_threads + | ||
322 | 3878 | srv_n_write_io_threads; | ||
323 | 3879 | |||
324 | 3880 | os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD, | ||
325 | 3881 | srv_n_read_io_threads, | ||
326 | 3882 | srv_n_write_io_threads, | ||
327 | 3883 | SRV_MAX_N_PENDING_SYNC_IOS); | ||
328 | 3884 | |||
329 | 3885 | fil_init(srv_file_per_table ? 50000 : 5000, | ||
330 | 3886 | srv_max_n_open_files); | ||
331 | 3887 | #endif | ||
332 | 3888 | |||
333 | 3889 | fsp_init(); | ||
334 | 3890 | |||
335 | 3891 | for (i = 0; i < srv_n_file_io_threads; i++) { | ||
336 | 3892 | thread_nr[i] = i; | ||
337 | 3893 | |||
338 | 3894 | os_thread_create(io_handler_thread, thread_nr + i, | ||
339 | 3895 | thread_ids + i); | ||
340 | 3896 | } | ||
341 | 3897 | |||
342 | 3898 | os_thread_sleep(200000); /*0.2 sec*/ | ||
343 | 3899 | |||
344 | 3900 | err = open_or_create_data_files(&create_new_db, | ||
345 | 3901 | #ifdef XTRADB_BASED | ||
346 | 3902 | &create_new_doublewrite_file, | ||
347 | 3903 | #endif | ||
348 | 3904 | &min_flushed_lsn, &max_flushed_lsn, | ||
349 | 3905 | &sum_of_new_sizes); | ||
350 | 3906 | if (err != DB_SUCCESS) { | ||
351 | 3907 | msg("xtrabackup: Could not open or create data files.\n" | ||
352 | 3908 | "xtrabackup: If you tried to add new data files, and it " | ||
353 | 3909 | "failed here,\n" | ||
354 | 3910 | "xtrabackup: you should now edit innodb_data_file_path in " | ||
355 | 3911 | "my.cnf back\n" | ||
356 | 3912 | "xtrabackup: to what it was, and remove the new ibdata " | ||
357 | 3913 | "files InnoDB created\n" | ||
358 | 3914 | "xtrabackup: in this failed attempt. InnoDB only wrote " | ||
359 | 3915 | "those files full of\n" | ||
360 | 3916 | "xtrabackup: zeros, but did not yet use them in any way. " | ||
361 | 3917 | "But be careful: do not\n" | ||
362 | 3918 | "xtrabackup: remove old data files which contain your " | ||
363 | 3919 | "precious data!\n"); | ||
364 | 3920 | return(err); | ||
365 | 3921 | } | ||
366 | 3922 | |||
367 | 3923 | /* create_new_db must not be TRUE.. */ | ||
368 | 3924 | if (create_new_db) { | ||
369 | 3925 | msg("xtrabackup: could not find data files at the " | ||
370 | 3926 | "specified datadir\n"); | ||
371 | 3927 | return(DB_ERROR); | ||
372 | 3928 | } | ||
373 | 3929 | |||
374 | 3930 | return(fil_load_single_table_tablespaces()); | ||
375 | 3931 | } | ||
376 | 3932 | |||
377 | 3933 | /************************************************************************ | ||
378 | 3934 | Destroy the tablespace memory cache. */ | ||
379 | 3935 | void | ||
380 | 3936 | xb_data_files_close(void) | ||
381 | 3937 | /*====================*/ | ||
382 | 3938 | { | ||
383 | 3939 | ulint i; | ||
384 | 3940 | |||
385 | 3941 | /* Shutdown the aio threads. This has been copied from | ||
386 | 3942 | innobase_shutdown_for_mysql(). */ | ||
387 | 3943 | |||
388 | 3944 | srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; | ||
389 | 3945 | |||
390 | 3946 | for (i = 0; i < 1000; i++) { | ||
391 | 3947 | os_aio_wake_all_threads_at_shutdown(); | ||
392 | 3948 | |||
393 | 3949 | os_mutex_enter(os_sync_mutex); | ||
394 | 3950 | |||
395 | 3951 | if (os_thread_count == 0) { | ||
396 | 3952 | |||
397 | 3953 | os_mutex_exit(os_sync_mutex); | ||
398 | 3954 | |||
399 | 3955 | os_thread_sleep(10000); | ||
400 | 3956 | |||
401 | 3957 | break; | ||
402 | 3958 | } | ||
403 | 3959 | |||
404 | 3960 | os_mutex_exit(os_sync_mutex); | ||
405 | 3961 | |||
406 | 3962 | os_thread_sleep(10000); | ||
407 | 3963 | } | ||
408 | 3964 | |||
409 | 3965 | if (i == 1000) { | ||
410 | 3966 | msg("xtrabackup: Warning: %lu threads created by InnoDB" | ||
411 | 3967 | " had not exited at shutdown!\n", | ||
412 | 3968 | (ulong) os_thread_count); | ||
413 | 3969 | } | ||
414 | 3970 | |||
415 | 3971 | #ifdef INNODB_VERSION_SHORT | ||
416 | 3972 | os_aio_free(); | ||
417 | 3973 | #endif | ||
418 | 3974 | fil_close_all_files(); | ||
419 | 3975 | #ifndef INNODB_VERSION_SHORT | ||
420 | 3976 | fil_free_all_spaces(); | ||
421 | 3977 | #endif | ||
422 | 3978 | fil_system = NULL; | ||
423 | 3979 | |||
424 | 3980 | srv_shutdown_state = SRV_SHUTDOWN_NONE; | ||
425 | 3981 | } | ||
426 | 3982 | |||
427 | 3747 | /*************************************************************************** | 3983 | /*************************************************************************** |
428 | 3748 | Creates an output directory for a given tablespace, if it does not exist */ | 3984 | Creates an output directory for a given tablespace, if it does not exist */ |
429 | 3749 | static | 3985 | static |
430 | @@ -4050,85 +4286,25 @@ | |||
431 | 4050 | srv_general_init(); | 4286 | srv_general_init(); |
432 | 4051 | 4287 | ||
433 | 4052 | { | 4288 | { |
434 | 4053 | ibool create_new_db; | ||
435 | 4054 | #ifdef XTRADB_BASED | ||
436 | 4055 | ibool create_new_doublewrite_file; | ||
437 | 4056 | #endif | ||
438 | 4057 | ibool log_file_created; | 4289 | ibool log_file_created; |
439 | 4058 | ibool log_created = FALSE; | 4290 | ibool log_created = FALSE; |
440 | 4059 | ibool log_opened = FALSE; | 4291 | ibool log_opened = FALSE; |
441 | 4060 | LSN64 min_flushed_lsn; | ||
442 | 4061 | LSN64 max_flushed_lsn; | ||
443 | 4062 | ulint sum_of_new_sizes; | ||
444 | 4063 | ulint err; | 4292 | ulint err; |
445 | 4064 | ulint i; | 4293 | ulint i; |
446 | 4065 | 4294 | ||
473 | 4066 | 4295 | err = xb_data_files_init(); | |
474 | 4067 | 4296 | if (err != DB_SUCCESS) { | |
475 | 4068 | 4297 | msg("xtrabackup: error: xb_data_files_init() failed with" | |
476 | 4069 | #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD | 4298 | "error code %lu\n", err); |
477 | 4070 | #define SRV_MAX_N_PENDING_SYNC_IOS 100 | 4299 | exit(EXIT_FAILURE); |
478 | 4071 | 4300 | } | |
479 | 4072 | #ifndef INNODB_VERSION_SHORT | 4301 | |
454 | 4073 | os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD | ||
455 | 4074 | * srv_n_file_io_threads, | ||
456 | 4075 | srv_n_file_io_threads, | ||
457 | 4076 | SRV_MAX_N_PENDING_SYNC_IOS); | ||
458 | 4077 | |||
459 | 4078 | fil_init(srv_max_n_open_files); | ||
460 | 4079 | #else | ||
461 | 4080 | srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads; | ||
462 | 4081 | |||
463 | 4082 | os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD, | ||
464 | 4083 | srv_n_read_io_threads, | ||
465 | 4084 | srv_n_write_io_threads, | ||
466 | 4085 | SRV_MAX_N_PENDING_SYNC_IOS); | ||
467 | 4086 | |||
468 | 4087 | fil_init(srv_file_per_table ? 50000 : 5000, | ||
469 | 4088 | srv_max_n_open_files); | ||
470 | 4089 | #endif | ||
471 | 4090 | |||
472 | 4091 | fsp_init(); | ||
480 | 4092 | log_init(); | 4302 | log_init(); |
481 | 4093 | 4303 | ||
482 | 4094 | lock_sys_create(srv_lock_table_size); | 4304 | lock_sys_create(srv_lock_table_size); |
483 | 4095 | 4305 | ||
484 | 4096 | for (i = 0; i < srv_n_file_io_threads; i++) { | ||
485 | 4097 | thread_nr[i] = i; | ||
486 | 4098 | |||
487 | 4099 | os_thread_create(io_handler_thread, thread_nr + i, thread_ids + i); | ||
488 | 4100 | } | ||
489 | 4101 | |||
490 | 4102 | os_thread_sleep(200000); /*0.2 sec*/ | ||
491 | 4103 | |||
492 | 4104 | err = open_or_create_data_files(&create_new_db, | ||
493 | 4105 | #ifdef XTRADB_BASED | ||
494 | 4106 | &create_new_doublewrite_file, | ||
495 | 4107 | #endif | ||
496 | 4108 | &min_flushed_lsn, &max_flushed_lsn, | ||
497 | 4109 | &sum_of_new_sizes); | ||
498 | 4110 | if (err != DB_SUCCESS) { | ||
499 | 4111 | msg( | ||
500 | 4112 | "xtrabackup: Could not open or create data files.\n" | ||
501 | 4113 | "xtrabackup: If you tried to add new data files, and it failed here,\n" | ||
502 | 4114 | "xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n" | ||
503 | 4115 | "xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n" | ||
504 | 4116 | "xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n" | ||
505 | 4117 | "xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n" | ||
506 | 4118 | "xtrabackup: remove old data files which contain your precious data!\n"); | ||
507 | 4119 | |||
508 | 4120 | //return((int) err); | ||
509 | 4121 | exit(EXIT_FAILURE); | ||
510 | 4122 | } | ||
511 | 4123 | |||
512 | 4124 | /* create_new_db must not be TRUE.. */ | ||
513 | 4125 | if (create_new_db) { | ||
514 | 4126 | msg("xtrabackup: Something wrong with source files...\n"); | ||
515 | 4127 | exit(EXIT_FAILURE); | ||
516 | 4128 | } | ||
517 | 4129 | |||
518 | 4130 | for (i = 0; i < srv_n_log_files; i++) { | 4306 | for (i = 0; i < srv_n_log_files; i++) { |
520 | 4131 | err = open_or_create_log_file(create_new_db, &log_file_created, | 4307 | err = open_or_create_log_file(FALSE, &log_file_created, |
521 | 4132 | log_opened, 0, i); | 4308 | log_opened, 0, i); |
522 | 4133 | if (err != DB_SUCCESS) { | 4309 | if (err != DB_SUCCESS) { |
523 | 4134 | 4310 | ||
524 | @@ -4141,8 +4317,7 @@ | |||
525 | 4141 | } else { | 4317 | } else { |
526 | 4142 | log_opened = TRUE; | 4318 | log_opened = TRUE; |
527 | 4143 | } | 4319 | } |
530 | 4144 | if ((log_opened && create_new_db) | 4320 | if ((log_opened && log_created)) { |
529 | 4145 | || (log_opened && log_created)) { | ||
531 | 4146 | msg( | 4321 | msg( |
532 | 4147 | "xtrabackup: Error: all log files must be created at the same time.\n" | 4322 | "xtrabackup: Error: all log files must be created at the same time.\n" |
533 | 4148 | "xtrabackup: All log files must be created also in database creation.\n" | 4323 | "xtrabackup: All log files must be created also in database creation.\n" |
534 | @@ -4162,8 +4337,6 @@ | |||
535 | 4162 | exit(EXIT_FAILURE); | 4337 | exit(EXIT_FAILURE); |
536 | 4163 | } | 4338 | } |
537 | 4164 | 4339 | ||
538 | 4165 | fil_load_single_table_tablespaces(); | ||
539 | 4166 | |||
540 | 4167 | } | 4340 | } |
541 | 4168 | 4341 | ||
542 | 4169 | /* create extra LSN dir if it does not exist. */ | 4342 | /* create extra LSN dir if it does not exist. */ |
543 | @@ -4545,6 +4718,8 @@ | |||
544 | 4545 | msg("xtrabackup: Transaction log of lsn (%llu) to (%llu) was copied.\n", | 4718 | msg("xtrabackup: Transaction log of lsn (%llu) to (%llu) was copied.\n", |
545 | 4546 | checkpoint_lsn_start, log_copy_scanned_lsn); | 4719 | checkpoint_lsn_start, log_copy_scanned_lsn); |
546 | 4547 | #endif | 4720 | #endif |
547 | 4721 | |||
548 | 4722 | xb_data_files_close(); | ||
549 | 4548 | } | 4723 | } |
550 | 4549 | 4724 | ||
551 | 4550 | /* ================= stats ================= */ | 4725 | /* ================= stats ================= */ |
552 | @@ -5434,6 +5609,154 @@ | |||
553 | 5434 | return TRUE; | 5609 | return TRUE; |
554 | 5435 | } | 5610 | } |
555 | 5436 | 5611 | ||
556 | 5612 | /*********************************************************************** | ||
557 | 5613 | Searches for matching tablespace file for given .delta file and space_id | ||
558 | 5614 | in given directory. When matching tablespace found, renames it to match the | ||
559 | 5615 | name of .delta file. If there was a tablespace with matching name and | ||
560 | 5616 | mismatching ID, renames it to xtrabackup_tmp_#ID.ibd. If there was no | ||
561 | 5617 | matching file, creates the new one. | ||
562 | 5618 | @return file handle of matched or created file */ | ||
563 | 5619 | static | ||
564 | 5620 | os_file_t | ||
565 | 5621 | xb_delta_open_matching_space( | ||
566 | 5622 | const char* dbname, /* in: path to destination database dir */ | ||
567 | 5623 | const char* name, /* in: name of delta file (without .delta) */ | ||
568 | 5624 | ulint space_id, /* in: space id of delta file */ | ||
569 | 5625 | ulint zip_size, /* in: zip_size of tablespace */ | ||
570 | 5626 | char* real_name, /* out: full path of destination file */ | ||
571 | 5627 | size_t real_name_len, /* out: buffer size for real_name */ | ||
572 | 5628 | ibool* success) /* out: indicates error. TRUE = success */ | ||
573 | 5629 | { | ||
574 | 5630 | char dest_dir[FN_REFLEN]; | ||
575 | 5631 | char dest_space_name[FN_REFLEN]; | ||
576 | 5632 | ibool ok; | ||
577 | 5633 | fil_space_t* fil_space; | ||
578 | 5634 | os_file_t file = 0; | ||
579 | 5635 | |||
580 | 5636 | ut_a(dbname || space_id == 0); | ||
581 | 5637 | |||
582 | 5638 | *success = FALSE; | ||
583 | 5639 | |||
584 | 5640 | if (dbname) { | ||
585 | 5641 | snprintf(dest_dir, FN_REFLEN, "%s/%s", | ||
586 | 5642 | xtrabackup_target_dir, dbname); | ||
587 | 5643 | srv_normalize_path_for_win(dest_dir); | ||
588 | 5644 | |||
589 | 5645 | snprintf(dest_space_name, FN_REFLEN, "./%s/%s", | ||
590 | 5646 | dbname, name); | ||
591 | 5647 | } else { | ||
592 | 5648 | snprintf(dest_dir, FN_REFLEN, "%s", xtrabackup_target_dir); | ||
593 | 5649 | srv_normalize_path_for_win(dest_dir); | ||
594 | 5650 | |||
595 | 5651 | snprintf(dest_space_name, FN_REFLEN, "./%s", name); | ||
596 | 5652 | } | ||
597 | 5653 | |||
598 | 5654 | snprintf(real_name, real_name_len, | ||
599 | 5655 | "%s/%s", | ||
600 | 5656 | xtrabackup_target_dir, dest_space_name); | ||
601 | 5657 | srv_normalize_path_for_win(real_name); | ||
602 | 5658 | |||
603 | 5659 | /* Create the database directory if it doesn't exist yet */ | ||
604 | 5660 | if (!os_file_create_directory(dest_dir, FALSE)) { | ||
605 | 5661 | msg("xtrabackup: error: cannot create dir %s\n", dest_dir); | ||
606 | 5662 | return file; | ||
607 | 5663 | } | ||
608 | 5664 | |||
609 | 5665 | mutex_enter(&fil_system->mutex); | ||
610 | 5666 | fil_space = xb_space_get_by_name(dest_space_name); | ||
611 | 5667 | mutex_exit(&fil_system->mutex); | ||
612 | 5668 | |||
613 | 5669 | if (fil_space != NULL) { | ||
614 | 5670 | if (fil_space->id == space_id) { | ||
615 | 5671 | /* we found matching space */ | ||
616 | 5672 | goto found; | ||
617 | 5673 | } else { | ||
618 | 5674 | |||
619 | 5675 | char tmpname[FN_REFLEN]; | ||
620 | 5676 | |||
621 | 5677 | snprintf(tmpname, FN_REFLEN, "./%s/xtrabackup_tmp_#%lu", | ||
622 | 5678 | dbname, fil_space->id); | ||
623 | 5679 | |||
624 | 5680 | msg("xtrabackup: Renaming %s to %s.ibd\n", | ||
625 | 5681 | fil_space->name, tmpname); | ||
626 | 5682 | |||
627 | 5683 | if (!fil_rename_tablespace(NULL, | ||
628 | 5684 | fil_space->id, tmpname)) | ||
629 | 5685 | { | ||
630 | 5686 | msg("xtrabackup: Cannot rename %s to %s\n", | ||
631 | 5687 | fil_space->name, tmpname); | ||
632 | 5688 | goto exit; | ||
633 | 5689 | } | ||
634 | 5690 | } | ||
635 | 5691 | } | ||
636 | 5692 | |||
637 | 5693 | mutex_enter(&fil_system->mutex); | ||
638 | 5694 | fil_space = xb_space_get_by_id(space_id); | ||
639 | 5695 | mutex_exit(&fil_system->mutex); | ||
640 | 5696 | if (fil_space != NULL) { | ||
641 | 5697 | char tmpname[FN_REFLEN]; | ||
642 | 5698 | |||
643 | 5699 | strncpy(tmpname, dest_space_name, FN_REFLEN); | ||
644 | 5700 | tmpname[strlen(tmpname) - 4] = 0; | ||
645 | 5701 | |||
646 | 5702 | msg("xtrabackup: Renaming %s to %s\n", | ||
647 | 5703 | fil_space->name, dest_space_name); | ||
648 | 5704 | |||
649 | 5705 | if (!fil_rename_tablespace(NULL, | ||
650 | 5706 | fil_space->id, tmpname)) | ||
651 | 5707 | { | ||
652 | 5708 | msg("xtrabackup: Cannot rename %s to %s\n", | ||
653 | 5709 | fil_space->name, dest_space_name); | ||
654 | 5710 | goto exit; | ||
655 | 5711 | } | ||
656 | 5712 | |||
657 | 5713 | goto found; | ||
658 | 5714 | } | ||
659 | 5715 | |||
660 | 5716 | /* no matching space found. create the new one */ | ||
661 | 5717 | |||
662 | 5718 | #ifdef INNODB_VERSION_SHORT | ||
663 | 5719 | if (!fil_space_create(dest_space_name, space_id, | ||
664 | 5720 | zip_size, FIL_TABLESPACE)) { | ||
665 | 5721 | #else | ||
666 | 5722 | if (!fil_space_create(dest_space_name, space_id, | ||
667 | 5723 | FIL_TABLESPACE)) { | ||
668 | 5724 | #endif | ||
669 | 5725 | msg("xtrabackup: Cannot create tablespace %s\n", | ||
670 | 5726 | dest_space_name); | ||
671 | 5727 | goto exit; | ||
672 | 5728 | } | ||
673 | 5729 | |||
674 | 5730 | file = xb_file_create_no_error_handling(real_name, OS_FILE_CREATE, | ||
675 | 5731 | OS_FILE_READ_WRITE, | ||
676 | 5732 | &ok); | ||
677 | 5733 | |||
678 | 5734 | if (ok) { | ||
679 | 5735 | *success = TRUE; | ||
680 | 5736 | } else { | ||
681 | 5737 | msg("xtrabackup: Cannot open file %s\n", real_name); | ||
682 | 5738 | } | ||
683 | 5739 | |||
684 | 5740 | goto exit; | ||
685 | 5741 | |||
686 | 5742 | found: | ||
687 | 5743 | /* open the file and return it's handle */ | ||
688 | 5744 | |||
689 | 5745 | file = xb_file_create_no_error_handling(real_name, OS_FILE_OPEN, | ||
690 | 5746 | OS_FILE_READ_WRITE, | ||
691 | 5747 | &ok); | ||
692 | 5748 | |||
693 | 5749 | if (ok) { | ||
694 | 5750 | *success = TRUE; | ||
695 | 5751 | } else { | ||
696 | 5752 | msg("xtrabackup: Cannot open file %s\n", real_name); | ||
697 | 5753 | } | ||
698 | 5754 | |||
699 | 5755 | exit: | ||
700 | 5756 | |||
701 | 5757 | return file; | ||
702 | 5758 | } | ||
703 | 5759 | |||
704 | 5437 | /************************************************************************ | 5760 | /************************************************************************ |
705 | 5438 | Applies a given .delta file to the corresponding data file. | 5761 | Applies a given .delta file to the corresponding data file. |
706 | 5439 | @return TRUE on success */ | 5762 | @return TRUE on success */ |
707 | @@ -5451,6 +5774,7 @@ | |||
708 | 5451 | char src_path[FN_REFLEN]; | 5774 | char src_path[FN_REFLEN]; |
709 | 5452 | char dst_path[FN_REFLEN]; | 5775 | char dst_path[FN_REFLEN]; |
710 | 5453 | char meta_path[FN_REFLEN]; | 5776 | char meta_path[FN_REFLEN]; |
711 | 5777 | char space_name[FN_REFLEN]; | ||
712 | 5454 | ibool success; | 5778 | ibool success; |
713 | 5455 | 5779 | ||
714 | 5456 | ibool last_buffer = FALSE; | 5780 | ibool last_buffer = FALSE; |
715 | @@ -5478,6 +5802,9 @@ | |||
716 | 5478 | } | 5802 | } |
717 | 5479 | dst_path[strlen(dst_path) - 6] = '\0'; | 5803 | dst_path[strlen(dst_path) - 6] = '\0'; |
718 | 5480 | 5804 | ||
719 | 5805 | strncpy(space_name, filename, FN_REFLEN); | ||
720 | 5806 | space_name[strlen(space_name) - 6] = 0; | ||
721 | 5807 | |||
722 | 5481 | if (!get_meta_path(src_path, meta_path)) { | 5808 | if (!get_meta_path(src_path, meta_path)) { |
723 | 5482 | goto error; | 5809 | goto error; |
724 | 5483 | } | 5810 | } |
725 | @@ -5517,36 +5844,11 @@ | |||
726 | 5517 | 5844 | ||
727 | 5518 | xb_file_set_nocache(src_file, src_path, "OPEN"); | 5845 | xb_file_set_nocache(src_file, src_path, "OPEN"); |
728 | 5519 | 5846 | ||
733 | 5520 | dst_file = xb_file_create_no_error_handling(dst_path, OS_FILE_OPEN, | 5847 | dst_file = xb_delta_open_matching_space( |
734 | 5521 | OS_FILE_READ_WRITE, | 5848 | dbname, space_name, info.space_id, |
735 | 5522 | &success); | 5849 | info.page_size == UNIV_PAGE_SIZE ? 0 : info.page_size, |
736 | 5523 | again: | 5850 | dst_path, sizeof(dst_path), &success); |
737 | 5524 | if (!success) { | 5851 | if (!success) { |
738 | 5525 | ulint errcode = os_file_get_last_error(TRUE); | ||
739 | 5526 | |||
740 | 5527 | if (errcode == OS_FILE_NOT_FOUND) { | ||
741 | 5528 | msg("xtrabackup: target data file %s " | ||
742 | 5529 | "is not found, creating a new one\n", dst_path); | ||
743 | 5530 | /* Create the database directory if it doesn't exist yet | ||
744 | 5531 | */ | ||
745 | 5532 | if (dbname) { | ||
746 | 5533 | char dst_dir[FN_REFLEN]; | ||
747 | 5534 | |||
748 | 5535 | snprintf(dst_dir, sizeof(dst_dir), "%s/%s", | ||
749 | 5536 | xtrabackup_real_target_dir, dbname); | ||
750 | 5537 | srv_normalize_path_for_win(dst_dir); | ||
751 | 5538 | |||
752 | 5539 | if (!os_file_create_directory(dst_dir, FALSE)) | ||
753 | 5540 | goto error; | ||
754 | 5541 | } | ||
755 | 5542 | dst_file = | ||
756 | 5543 | xb_file_create_no_error_handling(dst_path, | ||
757 | 5544 | OS_FILE_CREATE, | ||
758 | 5545 | OS_FILE_READ_WRITE, | ||
759 | 5546 | &success); | ||
760 | 5547 | goto again; | ||
761 | 5548 | } | ||
762 | 5549 | |||
763 | 5550 | msg("xtrabackup: error: cannot open %s\n", dst_path); | 5852 | msg("xtrabackup: error: cannot open %s\n", dst_path); |
764 | 5551 | goto error; | 5853 | goto error; |
765 | 5552 | } | 5854 | } |
766 | @@ -5563,7 +5865,7 @@ | |||
767 | 5563 | incremental_buffer = ut_align(incremental_buffer_base, | 5865 | incremental_buffer = ut_align(incremental_buffer_base, |
768 | 5564 | UNIV_PAGE_SIZE_MAX); | 5866 | UNIV_PAGE_SIZE_MAX); |
769 | 5565 | 5867 | ||
771 | 5566 | msg("Applying %s ...\n", src_path); | 5868 | msg("Applying %s to %s...\n", src_path, dst_path); |
772 | 5567 | 5869 | ||
773 | 5568 | while (!last_buffer) { | 5870 | while (!last_buffer) { |
774 | 5569 | ulint cluster_header; | 5871 | ulint cluster_header; |
775 | @@ -5873,6 +6175,8 @@ | |||
776 | 5873 | static void | 6175 | static void |
777 | 5874 | xtrabackup_prepare_func(void) | 6176 | xtrabackup_prepare_func(void) |
778 | 5875 | { | 6177 | { |
779 | 6178 | ulint err; | ||
780 | 6179 | |||
781 | 5876 | /* cd to target-dir */ | 6180 | /* cd to target-dir */ |
782 | 5877 | 6181 | ||
783 | 5878 | if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME))) | 6182 | if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME))) |
784 | @@ -5943,12 +6247,29 @@ | |||
785 | 5943 | if(xtrabackup_init_temp_log()) | 6247 | if(xtrabackup_init_temp_log()) |
786 | 5944 | goto error; | 6248 | goto error; |
787 | 5945 | 6249 | ||
789 | 5946 | if(xtrabackup_incremental && !xtrabackup_apply_deltas(TRUE)) | 6250 | if(innodb_init_param()) |
790 | 5947 | goto error; | 6251 | goto error; |
791 | 5948 | 6252 | ||
792 | 6253 | mem_init(srv_mem_pool_size); | ||
793 | 6254 | if (xtrabackup_incremental) { | ||
794 | 6255 | err = xb_data_files_init(); | ||
795 | 6256 | if (err != DB_SUCCESS) { | ||
796 | 6257 | msg("xtrabackup: error: xb_data_files_init() failed with" | ||
797 | 6258 | "error code %lu\n", err); | ||
798 | 6259 | goto error; | ||
799 | 6260 | } | ||
800 | 6261 | |||
801 | 6262 | if(!xtrabackup_apply_deltas(TRUE)) { | ||
802 | 6263 | xb_data_files_close(); | ||
803 | 6264 | goto error; | ||
804 | 6265 | } | ||
805 | 6266 | |||
806 | 6267 | xb_data_files_close(); | ||
807 | 6268 | } | ||
808 | 5949 | sync_close(); | 6269 | sync_close(); |
809 | 5950 | sync_initialized = FALSE; | 6270 | sync_initialized = FALSE; |
810 | 5951 | os_sync_free(); | 6271 | os_sync_free(); |
811 | 6272 | mem_close(); | ||
812 | 5952 | os_sync_mutex = NULL; | 6273 | os_sync_mutex = NULL; |
813 | 5953 | ut_free_all_mem(); | 6274 | ut_free_all_mem(); |
814 | 5954 | 6275 | ||
815 | 5955 | 6276 | ||
816 | === added file 'test/t/bug932623.sh' | |||
817 | --- test/t/bug932623.sh 1970-01-01 00:00:00 +0000 | |||
818 | +++ test/t/bug932623.sh 2012-07-18 15:36:21 +0000 | |||
819 | @@ -0,0 +1,85 @@ | |||
820 | 1 | ######################################################################## | ||
821 | 2 | # Bug #932623: RENAME TABLE causes incremental prepare to fail | ||
822 | 3 | ######################################################################## | ||
823 | 4 | |||
824 | 5 | . inc/common.sh | ||
825 | 6 | |||
826 | 7 | start_server --innodb_file_per_table | ||
827 | 8 | |||
828 | 9 | run_cmd $MYSQL $MYSQL_ARGS test <<EOF | ||
829 | 10 | CREATE TABLE t1_old(a INT) ENGINE=InnoDB; | ||
830 | 11 | INSERT INTO t1_old VALUES (1), (2), (3); | ||
831 | 12 | |||
832 | 13 | CREATE TABLE t1(a INT) ENGINE=InnoDB; | ||
833 | 14 | INSERT INTO t1 VALUES (4), (5), (6); | ||
834 | 15 | EOF | ||
835 | 16 | |||
836 | 17 | # Full backup | ||
837 | 18 | # backup root directory | ||
838 | 19 | vlog "Starting backup" | ||
839 | 20 | innobackupex --no-timestamp $topdir/full | ||
840 | 21 | |||
841 | 22 | vlog "Rotating the table" | ||
842 | 23 | |||
843 | 24 | run_cmd $MYSQL $MYSQL_ARGS test <<EOF | ||
844 | 25 | CREATE TABLE t1_new(a int) ENGINE=InnoDB; | ||
845 | 26 | INSERT INTO t1_new VALUES (7), (8), (9); | ||
846 | 27 | |||
847 | 28 | CREATE DATABASE db2; | ||
848 | 29 | RENAME TABLE t1_old TO db2.t1; | ||
849 | 30 | |||
850 | 31 | RENAME TABLE t1 TO t1_old; | ||
851 | 32 | RENAME TABLE t1_new TO t1; | ||
852 | 33 | |||
853 | 34 | INSERT INTO t1_old VALUES (10), (11), (12); | ||
854 | 35 | INSERT INTO t1 VALUES (13), (14), (15); | ||
855 | 36 | |||
856 | 37 | EOF | ||
857 | 38 | |||
858 | 39 | vlog "Creating incremental backup" | ||
859 | 40 | |||
860 | 41 | innobackupex --incremental --no-timestamp \ | ||
861 | 42 | --incremental-basedir=$topdir/full $topdir/inc | ||
862 | 43 | |||
863 | 44 | vlog "Preparing backup" | ||
864 | 45 | |||
865 | 46 | innobackupex --apply-log --redo-only $topdir/full | ||
866 | 47 | vlog "Log applied to full backup" | ||
867 | 48 | |||
868 | 49 | innobackupex --apply-log --redo-only --incremental-dir=$topdir/inc \ | ||
869 | 50 | $topdir/full | ||
870 | 51 | vlog "Delta applied to full backup" | ||
871 | 52 | |||
872 | 53 | innobackupex --apply-log $topdir/full | ||
873 | 54 | vlog "Data prepared for restore" | ||
874 | 55 | |||
875 | 56 | checksum_t1_a=`checksum_table test t1` | ||
876 | 57 | checksum_t1_old_a=`checksum_table test t1_old` | ||
877 | 58 | checksum_t1_db2_a=`checksum_table db2 t1` | ||
878 | 59 | |||
879 | 60 | # Destroying mysql data | ||
880 | 61 | stop_server | ||
881 | 62 | rm -rf $mysql_datadir/* | ||
882 | 63 | vlog "Data destroyed" | ||
883 | 64 | |||
884 | 65 | # Restore backup | ||
885 | 66 | vlog "Copying files" | ||
886 | 67 | |||
887 | 68 | innobackupex --copy-back $topdir/full | ||
888 | 69 | vlog "Data restored" | ||
889 | 70 | |||
890 | 71 | start_server --innodb_file_per_table | ||
891 | 72 | |||
892 | 73 | vlog "Checking checksums" | ||
893 | 74 | checksum_t1_b=`checksum_table test t1` | ||
894 | 75 | checksum_t1_old_b=`checksum_table test t1_old` | ||
895 | 76 | checksum_t1_db2_b=`checksum_table db2 t1` | ||
896 | 77 | |||
897 | 78 | if [ "$checksum_t1_a" != "$checksum_t1_b" -o "$checksum_t1_old_a" != "$checksum_t1_old_b" \ | ||
898 | 79 | -o "$checksum_t1_db2_a" != "$checksum_t1_db2_b" ] | ||
899 | 80 | then | ||
900 | 81 | vlog "Checksums do not match" | ||
901 | 82 | exit -1 | ||
902 | 83 | fi | ||
903 | 84 | |||
904 | 85 | vlog "Checksums are OK" |
Sergei,
Tables may be renamed into another database directory, which this fix doesn't take into account. I think we should do space ID verification in a different way:
let's initialize fil_system, in the same --backup or --prepare does it and then use fil_space_ get_by_ id() and possibly fil_space_ get_by_ name().
Now the problem is that fil_system will also be initialized later in --prepare when innodb_init() is called, and initializing fil_system multiple times in the same process is tricky. I had to write some extra code for that in the compact backups branch, see xb_data_ files_init( ) and xb_data_ files_close( ) in lp:~akopytov/percona-xtrabackup/compact-backups.
Other minor things: inc/ibdata1. meta" in the test case was probably just for debugging and doesn't make any sense as far as regression testing is concerned.
- s/matchong/matching
- "cat $topdir/