Merge lp:~akopytov/percona-xtrabackup/bugs-1177206-and-1187071-2.0 into lp:percona-xtrabackup/2.0

Proposed by Alexey Kopytov
Status: Merged
Approved by: Laurynas Biveinis
Approved revision: no longer in the source branch.
Merged at revision: 564
Proposed branch: lp:~akopytov/percona-xtrabackup/bugs-1177206-and-1187071-2.0
Merge into: lp:percona-xtrabackup/2.0
Diff against target: 366 lines (+137/-44)
2 files modified
patches/innodb56.patch (+91/-22)
src/xtrabackup.cc (+46/-22)
To merge this branch: bzr merge lp:~akopytov/percona-xtrabackup/bugs-1177206-and-1187071-2.0
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Review via email: mp+170240@code.launchpad.net

Description of the change

    Bug #1177206: InnoDB: Assertion failure in thread <nr> in file
                  log0recv.c line 1105 InnoDB: Failing assertion: !page
                  || (ibool)!!page_is_comp(page) ==
                  dict_table_is_comp(index->table)

    Bug #1187071: xb 2.1 against ps 5.6 gives Error: Tablespace is not
                  sensible during backup"

    The problems are related, so fixing in a single revision.

    The problem in bug #1187071 was a difference in behavior between InnoDB
    5.5- and 5.6 codebases in cases when a newly created tablespace has
    uninitialized first page at the time when XtraBackup opens it while
    creating a list of tablespaces to backup. 5.1/5.5 InnoDB code would just
    complain about tablespace ID being non-sensible and omit it from the
    backup. But in 5.6 it fails with an error in such a case.

    A related problem in bug #1177206 was that
    xb_data_files_init() (i.e. loading tablespaces into fil_system) was
    called before log copying was started. This could lead to a race between
    the datafiles state in the resulting backup and xtrabackup_logfile: a
    tablespace created at a sensitive time would be missing in both the
    backup itself and as the corresponding MLOG_FILE_CREATE* log record in
    xtrabackup_logfile, so it would not be created on --apply-log
    either. This problem has existed since the very first XtraBackup
    version.

    Fixed by:

    1. Ignoring tablespaces with uninitialized pages on xtrabackup startup
    for InnoDB 5.6 codebase to match the behavior of InnoDB 5.5-.
    2. Moving the call to xb_data_files_init() in xtrabackup_backup_func()
    to a later stage so that it is only called after the log copying is
    started. This involved a minor code refactoring, since
    xb_data_files_init() previously did 2 things: initializing the 'fil'
    subsystem (which is also required by the log copying code) and actually
    populating fil_system. We now have 2 separate functions:
    xb_fil_io_init() (called before log copying is started) and
    xb_load_tablespaces() (called after log copying is started).

http://jenkins.percona.com/view/XtraBackup/job/percona-xtrabackup-2.0-param/461/

To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Was

13 ++ fsp_open_info* fsp;
14 ++ ulong minimum_size;
15 ++ ibool file_space_create_success;

intentional?

It looks like it's unrelated to the fix, just increases the patch size.

review: Needs Information
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Nevermind, I guess it's to fix "goto jumps past var initialization" warnings, isn't it?

review: Approve
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Exactly. Was something like "jump to protected scope" with clang.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'patches/innodb56.patch'
2--- patches/innodb56.patch 2013-05-16 18:01:50 +0000
3+++ patches/innodb56.patch 2013-06-19 05:51:29 +0000
4@@ -330,7 +330,17 @@
5
6 err = DB_CORRUPTION;
7
8-@@ -4018,6 +4141,9 @@
9+@@ -3974,6 +4097,9 @@
10+ #ifdef UNIV_HOTBACKUP
11+ fil_space_t* space;
12+ #endif
13++ fsp_open_info* fsp;
14++ ulong minimum_size;
15++ ibool file_space_create_success;
16+
17+ memset(&def, 0, sizeof(def));
18+ memset(&remote, 0, sizeof(remote));
19+@@ -4018,6 +4144,9 @@
20 # endif /* !UNIV_HOTBACKUP */
21 #endif
22
23@@ -340,24 +350,76 @@
24 /* Check for a link file which locates a remote tablespace. */
25 remote.success = fil_open_linked_file(
26 tablename, &remote.filepath, &remote.file);
27-@@ -4030,6 +4156,7 @@
28+@@ -4028,8 +4157,20 @@
29+ if (!remote.success) {
30+ os_file_close(remote.file);
31 mem_free(remote.filepath);
32++
33++ if (srv_backup_mode) {
34++
35++ /* Ignore files that have uninitialized space
36++ IDs on the backup stage. This means that a
37++ tablespace has just been created and we will
38++ replay the corresponding log records on
39++ prepare. */
40++
41++ goto func_exit_after_close;
42++ }
43 }
44 }
45 + }
46
47
48 /* Try to open the tablespace in the datadir. */
49-@@ -4135,7 +4262,7 @@
50+@@ -4042,6 +4183,17 @@
51+ fil_validate_single_table_tablespace(tablename, &def);
52+ if (!def.success) {
53+ os_file_close(def.file);
54++
55++ if (srv_backup_mode) {
56++
57++ /* Ignore files that have uninitialized space
58++ IDs on the backup stage. This means that a
59++ tablespace has just been created and we will
60++ replay the corresponding log records on
61++ prepare. */
62++
63++ goto func_exit_after_close;
64++ }
65+ }
66+ }
67+
68+@@ -4114,7 +4266,7 @@
69+ /* At this point, only one tablespace is open */
70+ ut_a(def.success == !remote.success);
71+
72+- fsp_open_info* fsp = def.success ? &def : &remote;
73++ fsp = def.success ? &def : &remote;
74+
75+ /* Get and test the file size. */
76+ size = os_file_get_size(fsp->file);
77+@@ -4133,9 +4285,9 @@
78+
79+ /* Every .ibd file is created >= 4 pages in size. Smaller files
80 cannot be ok. */
81- ulong minimum_size = FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE;
82+- ulong minimum_size = FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE;
83++ minimum_size = FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE;
84 if (size < minimum_size) {
85 -#ifndef UNIV_HOTBACKUP
86 +#if 0
87 ib_logf(IB_LOG_LEVEL_ERROR,
88 "The size of single-table tablespace file %s "
89 "is only " UINT64PF ", should be at least %lu!",
90-@@ -4243,7 +4370,51 @@
91+@@ -4216,7 +4368,7 @@
92+ }
93+ mutex_exit(&fil_system->mutex);
94+ #endif /* UNIV_HOTBACKUP */
95+- ibool file_space_create_success = fil_space_create(
96++ file_space_create_success = fil_space_create(
97+ tablename, fsp->id, fsp->flags, FIL_TABLESPACE);
98+
99+ if (!file_space_create_success) {
100+@@ -4243,13 +4395,55 @@
101 }
102
103 func_exit:
104@@ -408,9 +470,16 @@
105 + os_file_close(fsp->file);
106 + }
107
108- #ifdef UNIV_HOTBACKUP
109+-#ifdef UNIV_HOTBACKUP
110 func_exit_after_close:
111-@@ -4263,7 +4434,7 @@
112+-#else
113+ ut_ad(!mutex_own(&fil_system->mutex));
114+-#endif
115++
116+ mem_free(tablename);
117+ if (remote.success) {
118+ mem_free(remote.filepath);
119+@@ -4263,7 +4457,7 @@
120 idea is to read as much good data as we can and jump over bad data.
121 @return 0 if ok, -1 if error even after the retries, 1 if at the end
122 of the directory */
123@@ -419,7 +488,7 @@
124 int
125 fil_file_readdir_next_file(
126 /*=======================*/
127-@@ -4303,7 +4474,7 @@
128+@@ -4303,7 +4497,7 @@
129 @return DB_SUCCESS or error number */
130 UNIV_INTERN
131 dberr_t
132@@ -428,7 +497,7 @@
133 /*===================================*/
134 {
135 int ret;
136-@@ -4359,7 +4530,9 @@
137+@@ -4359,7 +4553,9 @@
138 "%s/%s", fil_path_to_mysql_datadir, dbinfo.name);
139 srv_normalize_path_for_win(dbpath);
140
141@@ -439,7 +508,7 @@
142
143 if (dbdir != NULL) {
144
145-@@ -4380,9 +4553,15 @@
146+@@ -4380,9 +4576,15 @@
147 && (0 == strcmp(fileinfo.name
148 + strlen(fileinfo.name) - 4,
149 ".ibd")
150@@ -457,7 +526,7 @@
151 /* The name ends in .ibd or .isl;
152 try opening the file */
153 fil_load_single_table_tablespace(
154-@@ -4538,6 +4717,7 @@
155+@@ -4538,6 +4740,7 @@
156 {
157 fil_space_t* fnamespace;
158 fil_space_t* space;
159@@ -465,7 +534,7 @@
160
161 ut_ad(fil_system);
162
163-@@ -4615,6 +4795,10 @@
164+@@ -4615,6 +4818,10 @@
165 if (fnamespace == NULL) {
166 if (print_error_if_does_not_exist) {
167 fil_report_missing_tablespace(name, id);
168@@ -476,7 +545,7 @@
169 }
170 } else {
171 ut_print_timestamp(stderr);
172-@@ -4638,6 +4822,10 @@
173+@@ -4638,6 +4845,10 @@
174
175 mutex_exit(&fil_system->mutex);
176
177@@ -487,7 +556,7 @@
178 return(FALSE);
179 }
180
181-@@ -4728,6 +4916,7 @@
182+@@ -4728,6 +4939,7 @@
183 ulint page_size;
184 ulint pages_added;
185 ibool success;
186@@ -495,7 +564,7 @@
187
188 ut_ad(!srv_read_only_mode);
189
190-@@ -4772,13 +4961,17 @@
191+@@ -4772,13 +4984,17 @@
192 goto retry;
193 }
194
195@@ -514,7 +583,7 @@
196 start_page_no = space->size;
197 file_start_page_no = space->size - node->size;
198
199-@@ -5024,7 +5217,7 @@
200+@@ -5024,7 +5240,7 @@
201 off the LRU list if it is in the LRU list. The caller must hold the fil_sys
202 mutex. */
203 static
204@@ -523,7 +592,7 @@
205 fil_node_prepare_for_io(
206 /*====================*/
207 fil_node_t* node, /*!< in: file node */
208-@@ -5044,9 +5237,12 @@
209+@@ -5044,9 +5260,12 @@
210 }
211
212 if (node->open == FALSE) {
213@@ -537,7 +606,7 @@
214 }
215
216 if (node->n_pending == 0 && fil_space_belongs_in_lru(space)) {
217-@@ -5058,6 +5254,8 @@
218+@@ -5058,6 +5277,8 @@
219 }
220
221 node->n_pending++;
222@@ -546,7 +615,7 @@
223 }
224
225 /********************************************************************//**
226-@@ -5259,6 +5457,16 @@
227+@@ -5259,6 +5480,16 @@
228
229 ut_ad(mode != OS_AIO_IBUF || space->purpose == FIL_TABLESPACE);
230
231@@ -563,7 +632,7 @@
232 node = UT_LIST_GET_FIRST(space->chain);
233
234 for (;;) {
235-@@ -5290,7 +5498,11 @@
236+@@ -5290,7 +5521,11 @@
237 }
238
239 /* Open file if closed */
240@@ -576,7 +645,7 @@
241
242 /* Check that at least the start offset is within the bounds of a
243 single-table tablespace, including rollback tablespaces. */
244-@@ -6164,6 +6376,7 @@
245+@@ -6164,6 +6399,7 @@
246 return(err);
247 }
248
249@@ -584,7 +653,7 @@
250 /****************************************************************//**
251 Generate redo logs for swapping two .ibd files */
252 UNIV_INTERN
253-@@ -6187,4 +6400,4 @@
254+@@ -6187,4 +6423,4 @@
255 0, 0, new_name, old_name, &mtr);
256 mtr_commit(&mtr);
257 }
258
259=== modified file 'src/xtrabackup.cc'
260--- src/xtrabackup.cc 2013-05-16 18:01:50 +0000
261+++ src/xtrabackup.cc 2013-06-19 05:51:29 +0000
262@@ -4826,24 +4826,12 @@
263 }
264
265 /************************************************************************
266-Initialize the tablespace memory cache and populate it by scanning for and
267-opening data files.
268-@returns DB_SUCCESS or error code.*/
269+Initializes the I/O and tablespace cache subsystems. */
270 static
271-ulint
272-xb_data_files_init(void)
273-/*====================*/
274+void
275+xb_fil_io_init(void)
276+/*================*/
277 {
278- ulint i;
279- ibool create_new_db;
280-#ifdef XTRADB_BASED
281- ibool create_new_doublewrite_file;
282-#endif
283- ulint err;
284- lsn_t min_flushed_lsn;
285- lsn_t max_flushed_lsn;
286- ulint sum_of_new_sizes;
287-
288 #ifndef INNODB_VERSION_SHORT
289 os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
290 * srv_n_file_io_threads,
291@@ -4868,6 +4856,25 @@
292 #endif
293
294 fsp_init();
295+}
296+
297+/****************************************************************************
298+Populates the tablespace memory cache by scanning for and opening data files.
299+@returns DB_SUCCESS or error code.*/
300+static
301+ulint
302+xb_load_tablespaces(void)
303+/*=====================*/
304+{
305+ ulint i;
306+ ibool create_new_db;
307+#ifdef XTRADB_BASED
308+ ibool create_new_doublewrite_file;
309+#endif
310+ ulint err;
311+ lsn_t min_flushed_lsn;
312+ lsn_t max_flushed_lsn;
313+ ulint sum_of_new_sizes;
314
315 for (i = 0; i < srv_n_file_io_threads; i++) {
316 thread_nr[i] = i;
317@@ -4932,6 +4939,20 @@
318 return(DB_SUCCESS);
319 }
320
321+/************************************************************************
322+Initialize the tablespace memory cache and populate it by scanning for and
323+opening data files.
324+@returns DB_SUCCESS or error code.*/
325+static
326+ulint
327+xb_data_files_init(void)
328+/*====================*/
329+{
330+ xb_fil_io_init();
331+
332+ return(xb_load_tablespaces());
333+}
334+
335 /*********************************************************************//**
336 Normalizes init parameter values to use units we use inside InnoDB.
337 @return DB_SUCCESS or error code */
338@@ -5438,12 +5459,7 @@
339 ulint err;
340 ulint i;
341
342- err = xb_data_files_init();
343- if (err != DB_SUCCESS) {
344- msg("xtrabackup: error: xb_data_files_init() failed with"
345- "error code %lu\n", err);
346- exit(EXIT_FAILURE);
347- }
348+ xb_fil_io_init();
349
350 log_init();
351
352@@ -5655,6 +5671,14 @@
353 log_copying_stop = xb_os_event_create(NULL);
354 os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
355
356+ /* Populate fil_system with tablespaces to copy */
357+ err = xb_load_tablespaces();
358+ if (err != DB_SUCCESS) {
359+ msg("xtrabackup: error: xb_load_tablespaces() failed with"
360+ "error code %lu\n", err);
361+ exit(EXIT_FAILURE);
362+ }
363+
364 if (xtrabackup_parallel > 1 && xtrabackup_stream &&
365 xtrabackup_stream_fmt == XB_STREAM_FMT_TAR) {
366 msg("xtrabackup: warning: the --parallel option does not have "

Subscribers

People subscribed via source and target branches