Merge lp:~percona-toolkit-dev/percona-toolkit/fix-1047335-crashed-tables into lp:percona-toolkit/2.1
- fix-1047335-crashed-tables
- Merge into 2.1
Status: | Superseded |
---|---|
Proposed branch: | lp:~percona-toolkit-dev/percona-toolkit/fix-1047335-crashed-tables |
Merge into: | lp:percona-toolkit/2.1 |
Diff against target: |
593 lines (+232/-68) 18 files modified
bin/pt-archiver (+2/-4) bin/pt-config-diff (+3/-1) bin/pt-duplicate-key-checker (+14/-5) bin/pt-find (+2/-4) bin/pt-heartbeat (+2/-4) bin/pt-index-usage (+14/-5) bin/pt-kill (+5/-5) bin/pt-online-schema-change (+5/-5) bin/pt-query-advisor (+2/-4) bin/pt-query-digest (+2/-4) bin/pt-table-checksum (+14/-5) bin/pt-table-sync (+2/-2) bin/pt-upgrade (+2/-4) lib/SchemaIterator.pm (+16/-1) lib/TableParser.pm (+2/-8) t/lib/SchemaIterator.t (+70/-2) t/lib/TableParser.t (+64/-5) t/lib/samples/bug_1047335_crashed_table.sql (+11/-0) |
To merge this branch: | bzr merge lp:~percona-toolkit-dev/percona-toolkit/fix-1047335-crashed-tables |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Nichter | Needs Resubmitting | ||
Review via email: mp+132185@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-10-30.
Commit message
Description of the change
Daniel Nichter (daniel-nichter) wrote : | # |
Daniel Nichter (daniel-nichter) wrote : | # |
Also, the local $EVAL_ERROR (re another branch).
I think we have a crashed .frm in the source somewhere; I just looked but couldn't find it; I recall testing this before for something else.
Re 469 +# This might fail. Doesn't matter -- stop_sandbox will just rm -rf the folder -- will this cause output to STDERR? If so, that's bad because it shows up as an error.
- 436. By Brian Fraser
-
Fix for 1047335: SchemaIterator fails when it encounters a crashed table
- 437. By Brian Fraser
-
Removed local $EVAL_ERROR, added a test using t/lib/samples/
broken_ tbl.frm, and updated all modules - 438. By Brian Fraser
-
Fixes per Daniel's review
- 439. By Brian Fraser
-
t/lib/samples/
bug_1047335_ crashed_ table.sql: Use a single INSERT with all the values instead of 1k statements
Unmerged revisions
Preview Diff
1 | === modified file 'bin/pt-archiver' |
2 | --- bin/pt-archiver 2012-10-22 18:17:08 +0000 |
3 | +++ bin/pt-archiver 2012-10-30 21:38:20 +0000 |
4 | @@ -1584,13 +1584,11 @@ |
5 | PTDEBUG && _d($show_sql); |
6 | my $href; |
7 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
8 | - if ( $EVAL_ERROR ) { |
9 | - PTDEBUG && _d($EVAL_ERROR); |
10 | - |
11 | + if ( my $e = $EVAL_ERROR ) { |
12 | PTDEBUG && _d($old_sql_mode); |
13 | $dbh->do($old_sql_mode); |
14 | |
15 | - return; |
16 | + die $e; |
17 | } |
18 | |
19 | PTDEBUG && _d($old_sql_mode); |
20 | |
21 | === modified file 'bin/pt-config-diff' |
22 | --- bin/pt-config-diff 2012-10-22 18:17:08 +0000 |
23 | +++ bin/pt-config-diff 2012-10-30 21:38:20 +0000 |
24 | @@ -1576,7 +1576,9 @@ |
25 | PTDEBUG && _d($sql); |
26 | my $row = $self->{dbh}->selectrow_arrayref($sql); |
27 | PTDEBUG && _d(defined $row ? @$row : 'undef'); |
28 | - $self->{is_cluster_node} = $row && $row->[0] ? 1 : 0; |
29 | + $self->{is_cluster_node} = $row && $row->[1] |
30 | + ? ($row->[1] eq 'ON' || $row->[1] eq '1') |
31 | + : 0; |
32 | |
33 | return $self->{is_cluster_node}; |
34 | } |
35 | |
36 | === modified file 'bin/pt-duplicate-key-checker' |
37 | --- bin/pt-duplicate-key-checker 2012-10-22 18:17:08 +0000 |
38 | +++ bin/pt-duplicate-key-checker 2012-10-30 21:38:20 +0000 |
39 | @@ -226,13 +226,11 @@ |
40 | PTDEBUG && _d($show_sql); |
41 | my $href; |
42 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
43 | - if ( $EVAL_ERROR ) { |
44 | - PTDEBUG && _d($EVAL_ERROR); |
45 | - |
46 | + if ( my $e = $EVAL_ERROR ) { |
47 | PTDEBUG && _d($old_sql_mode); |
48 | $dbh->do($old_sql_mode); |
49 | |
50 | - return; |
51 | + die $e; |
52 | } |
53 | |
54 | PTDEBUG && _d($old_sql_mode); |
55 | @@ -3138,7 +3136,18 @@ |
56 | } |
57 | |
58 | while ( my $tbl = shift @{$self->{tbls}} ) { |
59 | - my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl); |
60 | + local $EVAL_ERROR; |
61 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
62 | + if ( my $e = $EVAL_ERROR ) { |
63 | + my $table_name = "$self->{db}.$tbl"; |
64 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
65 | + PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
66 | + } |
67 | + else { |
68 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
69 | + } |
70 | + next; |
71 | + } |
72 | my $tbl_struct = $tp->parse($ddl); |
73 | if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
74 | return { |
75 | |
76 | === modified file 'bin/pt-find' |
77 | --- bin/pt-find 2012-10-22 18:17:08 +0000 |
78 | +++ bin/pt-find 2012-10-30 21:38:20 +0000 |
79 | @@ -1623,13 +1623,11 @@ |
80 | PTDEBUG && _d($show_sql); |
81 | my $href; |
82 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
83 | - if ( $EVAL_ERROR ) { |
84 | - PTDEBUG && _d($EVAL_ERROR); |
85 | - |
86 | + if ( my $e = $EVAL_ERROR ) { |
87 | PTDEBUG && _d($old_sql_mode); |
88 | $dbh->do($old_sql_mode); |
89 | |
90 | - return; |
91 | + die $e; |
92 | } |
93 | |
94 | PTDEBUG && _d($old_sql_mode); |
95 | |
96 | === modified file 'bin/pt-heartbeat' |
97 | --- bin/pt-heartbeat 2012-10-22 18:17:08 +0000 |
98 | +++ bin/pt-heartbeat 2012-10-30 21:38:20 +0000 |
99 | @@ -2549,13 +2549,11 @@ |
100 | PTDEBUG && _d($show_sql); |
101 | my $href; |
102 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
103 | - if ( $EVAL_ERROR ) { |
104 | - PTDEBUG && _d($EVAL_ERROR); |
105 | - |
106 | + if ( my $e = $EVAL_ERROR ) { |
107 | PTDEBUG && _d($old_sql_mode); |
108 | $dbh->do($old_sql_mode); |
109 | |
110 | - return; |
111 | + die $e; |
112 | } |
113 | |
114 | PTDEBUG && _d($old_sql_mode); |
115 | |
116 | === modified file 'bin/pt-index-usage' |
117 | --- bin/pt-index-usage 2012-10-22 18:17:08 +0000 |
118 | +++ bin/pt-index-usage 2012-10-30 21:38:20 +0000 |
119 | @@ -2821,13 +2821,11 @@ |
120 | PTDEBUG && _d($show_sql); |
121 | my $href; |
122 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
123 | - if ( $EVAL_ERROR ) { |
124 | - PTDEBUG && _d($EVAL_ERROR); |
125 | - |
126 | + if ( my $e = $EVAL_ERROR ) { |
127 | PTDEBUG && _d($old_sql_mode); |
128 | $dbh->do($old_sql_mode); |
129 | |
130 | - return; |
131 | + die $e; |
132 | } |
133 | |
134 | PTDEBUG && _d($old_sql_mode); |
135 | @@ -3968,7 +3966,18 @@ |
136 | } |
137 | |
138 | while ( my $tbl = shift @{$self->{tbls}} ) { |
139 | - my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl); |
140 | + local $EVAL_ERROR; |
141 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
142 | + if ( my $e = $EVAL_ERROR ) { |
143 | + my $table_name = "$self->{db}.$tbl"; |
144 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
145 | + PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
146 | + } |
147 | + else { |
148 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
149 | + } |
150 | + next; |
151 | + } |
152 | my $tbl_struct = $tp->parse($ddl); |
153 | if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
154 | return { |
155 | |
156 | === modified file 'bin/pt-kill' |
157 | --- bin/pt-kill 2012-10-22 18:17:08 +0000 |
158 | +++ bin/pt-kill 2012-10-30 21:38:20 +0000 |
159 | @@ -2499,13 +2499,11 @@ |
160 | PTDEBUG && _d($show_sql); |
161 | my $href; |
162 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
163 | - if ( $EVAL_ERROR ) { |
164 | - PTDEBUG && _d($EVAL_ERROR); |
165 | - |
166 | + if ( my $e = $EVAL_ERROR ) { |
167 | PTDEBUG && _d($old_sql_mode); |
168 | $dbh->do($old_sql_mode); |
169 | |
170 | - return; |
171 | + die $e; |
172 | } |
173 | |
174 | PTDEBUG && _d($old_sql_mode); |
175 | @@ -4807,7 +4805,9 @@ |
176 | PTDEBUG && _d($sql); |
177 | my $row = $self->{dbh}->selectrow_arrayref($sql); |
178 | PTDEBUG && _d(defined $row ? @$row : 'undef'); |
179 | - $self->{is_cluster_node} = $row && $row->[0] ? 1 : 0; |
180 | + $self->{is_cluster_node} = $row && $row->[1] |
181 | + ? ($row->[1] eq 'ON' || $row->[1] eq '1') |
182 | + : 0; |
183 | |
184 | return $self->{is_cluster_node}; |
185 | } |
186 | |
187 | === modified file 'bin/pt-online-schema-change' |
188 | --- bin/pt-online-schema-change 2012-10-22 20:23:05 +0000 |
189 | +++ bin/pt-online-schema-change 2012-10-30 21:38:20 +0000 |
190 | @@ -2733,13 +2733,11 @@ |
191 | PTDEBUG && _d($show_sql); |
192 | my $href; |
193 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
194 | - if ( $EVAL_ERROR ) { |
195 | - PTDEBUG && _d($EVAL_ERROR); |
196 | - |
197 | + if ( my $e = $EVAL_ERROR ) { |
198 | PTDEBUG && _d($old_sql_mode); |
199 | $dbh->do($old_sql_mode); |
200 | |
201 | - return; |
202 | + die $e; |
203 | } |
204 | |
205 | PTDEBUG && _d($old_sql_mode); |
206 | @@ -3437,7 +3435,9 @@ |
207 | PTDEBUG && _d($sql); |
208 | my $row = $self->{dbh}->selectrow_arrayref($sql); |
209 | PTDEBUG && _d(defined $row ? @$row : 'undef'); |
210 | - $self->{is_cluster_node} = $row && $row->[0] ? 1 : 0; |
211 | + $self->{is_cluster_node} = $row && $row->[1] |
212 | + ? ($row->[1] eq 'ON' || $row->[1] eq '1') |
213 | + : 0; |
214 | |
215 | return $self->{is_cluster_node}; |
216 | } |
217 | |
218 | === modified file 'bin/pt-query-advisor' |
219 | --- bin/pt-query-advisor 2012-10-22 18:17:08 +0000 |
220 | +++ bin/pt-query-advisor 2012-10-30 21:38:20 +0000 |
221 | @@ -5311,13 +5311,11 @@ |
222 | PTDEBUG && _d($show_sql); |
223 | my $href; |
224 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
225 | - if ( $EVAL_ERROR ) { |
226 | - PTDEBUG && _d($EVAL_ERROR); |
227 | - |
228 | + if ( my $e = $EVAL_ERROR ) { |
229 | PTDEBUG && _d($old_sql_mode); |
230 | $dbh->do($old_sql_mode); |
231 | |
232 | - return; |
233 | + die $e; |
234 | } |
235 | |
236 | PTDEBUG && _d($old_sql_mode); |
237 | |
238 | === modified file 'bin/pt-query-digest' |
239 | --- bin/pt-query-digest 2012-10-22 18:17:08 +0000 |
240 | +++ bin/pt-query-digest 2012-10-30 21:38:20 +0000 |
241 | @@ -8140,13 +8140,11 @@ |
242 | PTDEBUG && _d($show_sql); |
243 | my $href; |
244 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
245 | - if ( $EVAL_ERROR ) { |
246 | - PTDEBUG && _d($EVAL_ERROR); |
247 | - |
248 | + if ( my $e = $EVAL_ERROR ) { |
249 | PTDEBUG && _d($old_sql_mode); |
250 | $dbh->do($old_sql_mode); |
251 | |
252 | - return; |
253 | + die $e; |
254 | } |
255 | |
256 | PTDEBUG && _d($old_sql_mode); |
257 | |
258 | === modified file 'bin/pt-table-checksum' |
259 | --- bin/pt-table-checksum 2012-10-26 23:06:21 +0000 |
260 | +++ bin/pt-table-checksum 2012-10-30 21:38:20 +0000 |
261 | @@ -3725,13 +3725,11 @@ |
262 | PTDEBUG && _d($show_sql); |
263 | my $href; |
264 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
265 | - if ( $EVAL_ERROR ) { |
266 | - PTDEBUG && _d($EVAL_ERROR); |
267 | - |
268 | + if ( my $e = $EVAL_ERROR ) { |
269 | PTDEBUG && _d($old_sql_mode); |
270 | $dbh->do($old_sql_mode); |
271 | |
272 | - return; |
273 | + die $e; |
274 | } |
275 | |
276 | PTDEBUG && _d($old_sql_mode); |
277 | @@ -6784,7 +6782,18 @@ |
278 | } |
279 | |
280 | while ( my $tbl = shift @{$self->{tbls}} ) { |
281 | - my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl); |
282 | + local $EVAL_ERROR; |
283 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
284 | + if ( my $e = $EVAL_ERROR ) { |
285 | + my $table_name = "$self->{db}.$tbl"; |
286 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
287 | + PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
288 | + } |
289 | + else { |
290 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
291 | + } |
292 | + next; |
293 | + } |
294 | my $tbl_struct = $tp->parse($ddl); |
295 | if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
296 | return { |
297 | |
298 | === modified file 'bin/pt-table-sync' |
299 | --- bin/pt-table-sync 2012-10-22 18:17:08 +0000 |
300 | +++ bin/pt-table-sync 2012-10-30 21:38:20 +0000 |
301 | @@ -2990,7 +2990,7 @@ |
302 | my ( $self, $dbh, $quoter, $db, $tbl, $what ) = @_; |
303 | |
304 | if ( $what eq 'table' ) { |
305 | - my $ddl = $self->get_create_table($dbh, $quoter, $db, $tbl); |
306 | + my $ddl = $self->get_create_table($dbh, $dbh, $db, $tbl); |
307 | return unless $ddl; |
308 | if ( $ddl->[0] eq 'table' ) { |
309 | return $before |
310 | @@ -3033,7 +3033,7 @@ |
311 | } |
312 | } |
313 | elsif ( $what eq 'view' ) { |
314 | - my $ddl = $self->get_create_table($dbh, $quoter, $db, $tbl); |
315 | + my $ddl = $self->get_create_table($dbh, $dbh, $db, $tbl); |
316 | return '/*!50001 DROP TABLE IF EXISTS ' . $quoter->quote($tbl) . "*/;\n" |
317 | . '/*!50001 DROP VIEW IF EXISTS ' . $quoter->quote($tbl) . "*/;\n" |
318 | . '/*!50001 ' . $ddl->[1] . "*/;\n"; |
319 | |
320 | === modified file 'bin/pt-upgrade' |
321 | --- bin/pt-upgrade 2012-10-22 18:17:08 +0000 |
322 | +++ bin/pt-upgrade 2012-10-30 21:38:20 +0000 |
323 | @@ -498,13 +498,11 @@ |
324 | PTDEBUG && _d($show_sql); |
325 | my $href; |
326 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
327 | - if ( $EVAL_ERROR ) { |
328 | - PTDEBUG && _d($EVAL_ERROR); |
329 | - |
330 | + if ( my $e = $EVAL_ERROR ) { |
331 | PTDEBUG && _d($old_sql_mode); |
332 | $dbh->do($old_sql_mode); |
333 | |
334 | - return; |
335 | + die $e; |
336 | } |
337 | |
338 | PTDEBUG && _d($old_sql_mode); |
339 | |
340 | === modified file 'lib/SchemaIterator.pm' |
341 | --- lib/SchemaIterator.pm 2012-04-03 18:21:15 +0000 |
342 | +++ lib/SchemaIterator.pm 2012-10-30 21:38:20 +0000 |
343 | @@ -352,7 +352,22 @@ |
344 | } |
345 | |
346 | while ( my $tbl = shift @{$self->{tbls}} ) { |
347 | - my $ddl = $tp->get_create_table($dbh, $self->{db}, $tbl); |
348 | + local $EVAL_ERROR; |
349 | + my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) }; |
350 | + if ( my $e = $EVAL_ERROR ) { |
351 | + my $table_name = "$self->{db}.$tbl"; |
352 | + # SHOW CREATE TABLE failed. This is a bit puzzling; |
353 | + # maybe the table got dropped, or crashed. Not much we can |
354 | + # do about it; If the table is missing, just PTDEBUG it, but |
355 | + # otherwise, warn with the error. |
356 | + if ( $e =~ /\QTable '$table_name' doesn't exist/ ) { |
357 | + PTDEBUG && _d("Skipping $table_name because it no longer exists"); |
358 | + } |
359 | + else { |
360 | + warn "Skipping $table_name because SHOW CREATE TABLE failed: $e"; |
361 | + } |
362 | + next; |
363 | + } |
364 | my $tbl_struct = $tp->parse($ddl); |
365 | if ( $self->engine_is_allowed($tbl_struct->{engine}) ) { |
366 | return { |
367 | |
368 | === modified file 'lib/TableParser.pm' |
369 | --- lib/TableParser.pm 2012-10-19 23:14:07 +0000 |
370 | +++ lib/TableParser.pm 2012-10-30 21:38:20 +0000 |
371 | @@ -82,18 +82,12 @@ |
372 | PTDEBUG && _d($show_sql); |
373 | my $href; |
374 | eval { $href = $dbh->selectrow_hashref($show_sql); }; |
375 | - if ( $EVAL_ERROR ) { |
376 | - # TODO: I think we fail silently for tools which may try to call |
377 | - # this on temp tables, or don't care if the table goes away. We |
378 | - # should warn $EVAL_ERROR and require callers to eval us and do |
379 | - # what they want with the warning. |
380 | - PTDEBUG && _d($EVAL_ERROR); |
381 | - |
382 | + if ( my $e = $EVAL_ERROR ) { |
383 | # Restore old SQL mode. |
384 | PTDEBUG && _d($old_sql_mode); |
385 | $dbh->do($old_sql_mode); |
386 | |
387 | - return; |
388 | + die $e; |
389 | } |
390 | |
391 | # Restore old SQL mode. |
392 | |
393 | === modified file 't/lib/SchemaIterator.t' |
394 | --- t/lib/SchemaIterator.t 2012-06-07 03:14:20 +0000 |
395 | +++ t/lib/SchemaIterator.t 2012-10-30 21:38:20 +0000 |
396 | @@ -9,7 +9,7 @@ |
397 | use strict; |
398 | use warnings FATAL => 'all'; |
399 | use English qw(-no_match_vars); |
400 | -use Test::More tests => 30; |
401 | +use Test::More; |
402 | |
403 | use SchemaIterator; |
404 | use FileIterator; |
405 | @@ -407,7 +407,75 @@ |
406 | ); |
407 | |
408 | # ############################################################################# |
409 | +# Bug 1047335: pt-duplicate-key-checker fails when it encounters a crashed table |
410 | +# https://bugs.launchpad.net/percona-toolkit/+bug/1047335 |
411 | +# ############################################################################# |
412 | + |
413 | +use File::Spec; |
414 | + |
415 | +my $master3_port = 2900; |
416 | +diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`); |
417 | +diag(`$trunk/sandbox/start-sandbox master $master3_port >/dev/null`); |
418 | +my $dbh3 = $sb->get_dbh_for("master3"); |
419 | + |
420 | +$sb->load_file('master3', File::Spec->catfile(qw(t lib samples bug_1047335_crashed_table.sql))); |
421 | +my $sth = $dbh3->prepare("INSERT INTO bug_1047335.crashed_table (trx_id, etc) VALUES(?, ?)"); |
422 | +$sth->execute($_, $_ x 100) for 1..1000; |
423 | +$sth->finish(); |
424 | + |
425 | +# Create the SI object before crashing the table |
426 | +my $tmp_si = new SchemaIterator( |
427 | + dbh => $dbh3, |
428 | + OptionParser => $o, |
429 | + Quoter => $q, |
430 | + TableParser => $tp, |
431 | + # This is needed because the way we corrupt tables |
432 | + # accidentally removes the database from SHOW DATABASES |
433 | + db => 'bug_1047335', |
434 | + ); |
435 | + |
436 | +my $master_basedir = File::Spec->catdir(File::Spec->tmpdir(), $master3_port); |
437 | +my $db_dir = File::Spec->catdir($master_basedir, "data", "bug_1047335"); |
438 | +my $myi = glob(File::Spec->catfile($db_dir, "crashed_table.[Mm][Yy][Iy]")); |
439 | +my $frm = glob(File::Spec->catfile($db_dir, "crashed_table.[Ff][Rr][Mm]")); |
440 | + |
441 | +die "Cannot find .myi file for crashed_table" unless $myi && -f $myi; |
442 | + |
443 | +# Truncate the .myi file to corrupt it |
444 | +truncate($myi, 4096); |
445 | + |
446 | +use File::Slurp qw( prepend_file append_file write_file ); |
447 | + |
448 | +# Corrupt the .frm file |
449 | +open my $urand_fh, q{<}, "/dev/urandom" |
450 | + or die "Cannot open /dev/urandom"; |
451 | +prepend_file($frm, scalar(<$urand_fh>)); |
452 | +append_file($frm, scalar(<$urand_fh>)); |
453 | +close $urand_fh; |
454 | + |
455 | +$dbh3->do("FLUSH TABLES"); |
456 | +eval { $dbh3->do("SELECT etc FROM bug_1047335.crashed_table WHERE etc LIKE '10001' ORDER BY id ASC LIMIT 1") }; |
457 | + |
458 | +my $w = ''; |
459 | +{ |
460 | + local $SIG{__WARN__} = sub { $w .= shift }; |
461 | + 1 while $tmp_si->next(); |
462 | +} |
463 | + |
464 | +like( |
465 | + $w, |
466 | + qr/because SHOW CREATE TABLE failed:/, |
467 | + "->next() gives a warning if ->get_create_table dies from a strange error", |
468 | +); |
469 | + |
470 | +# This might fail. Doesn't matter -- stop_sandbox will just rm -rf the folder |
471 | +eval { $dbh3->do("DROP DATABASE IF EXISTS bug_1047335") }; |
472 | + |
473 | +diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`); |
474 | + |
475 | +# ############################################################################# |
476 | # Done. |
477 | # ############################################################################# |
478 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); |
479 | -exit; |
480 | + |
481 | +done_testing; |
482 | |
483 | === modified file 't/lib/TableParser.t' |
484 | --- t/lib/TableParser.t 2012-10-20 23:59:28 +0000 |
485 | +++ t/lib/TableParser.t 2012-10-30 21:38:20 +0000 |
486 | @@ -9,7 +9,7 @@ |
487 | use strict; |
488 | use warnings FATAL => 'all'; |
489 | use English qw(-no_match_vars); |
490 | -use Test::More tests => 40; |
491 | +use Test::More; |
492 | |
493 | use TableParser; |
494 | use Quoter; |
495 | @@ -32,10 +32,10 @@ |
496 | skip 'Sandbox master does not have the sakila database', 2 |
497 | unless @{$dbh->selectcol_arrayref("SHOW DATABASES LIKE 'sakila'")}; |
498 | |
499 | - is( |
500 | - $tp->get_create_table($dbh, 'sakila', 'FOO'), |
501 | - undef, |
502 | - "get_create_table(nonexistent table)" |
503 | + eval { $tp->get_create_table($dbh, 'sakila', 'FOO') }; |
504 | + ok( |
505 | + $EVAL_ERROR, |
506 | + "get_create_table(nonexistent table) dies" |
507 | ); |
508 | |
509 | my $ddl = $tp->get_create_table($dbh, 'sakila', 'actor'); |
510 | @@ -893,8 +893,67 @@ |
511 | ); |
512 | |
513 | # ############################################################################# |
514 | +# Bug 1047335: pt-duplicate-key-checker fails when it encounters a crashed table |
515 | +# https://bugs.launchpad.net/percona-toolkit/+bug/1047335 |
516 | +# ############################################################################# |
517 | + |
518 | +# We need to create a new server here, otherwise the whole test suite might die |
519 | +# if the crashed table can't be dropped. |
520 | + |
521 | +use File::Spec; |
522 | + |
523 | +my $master3_port = 2900; |
524 | +diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`); |
525 | +diag(`$trunk/sandbox/start-sandbox master $master3_port >/dev/null`); |
526 | +my $dbh3 = $sb->get_dbh_for("master3"); |
527 | + |
528 | +$sb->load_file('master3', File::Spec->catfile(qw(t lib samples bug_1047335_crashed_table.sql))); |
529 | +my $sth = $dbh3->prepare("INSERT INTO bug_1047335.crashed_table (trx_id, etc) VALUES(?, ?)"); |
530 | +$sth->execute($_, $_ x 100) for 1..1000; |
531 | +$sth->finish(); |
532 | + |
533 | + |
534 | +my $master_basedir = File::Spec->catdir(File::Spec->tmpdir(), $master3_port); |
535 | +my $db_dir = File::Spec->catdir($master_basedir, "data", "bug_1047335"); |
536 | +my $myi = glob(File::Spec->catfile($db_dir, "crashed_table.[Mm][Yy][Iy]")); |
537 | +my $frm = glob(File::Spec->catfile($db_dir, "crashed_table.[Ff][Rr][Mm]")); |
538 | + |
539 | +die "Cannot find .myi file for crashed_table" unless $myi && -f $myi; |
540 | + |
541 | +# Truncate the .myi file to corrupt it |
542 | +truncate($myi, 4096); |
543 | + |
544 | +# Corrupt the .frm file |
545 | +open my $urand_fh, q{<}, "/dev/urandom" |
546 | + or die "Cannot open /dev/urandom: $OS_ERROR"; |
547 | + |
548 | +open my $tmp_fh, q{>}, $frm |
549 | + or die "Cannot open $frm: $OS_ERROR"; |
550 | +print { $tmp_fh } scalar(<$urand_fh>), slurp_file($frm), scalar(<$urand_fh>); |
551 | +close $tmp_fh; |
552 | + |
553 | +close $urand_fh; |
554 | + |
555 | +$dbh3->do("FLUSH TABLES"); |
556 | +eval { $dbh3->do("SELECT etc FROM bug_1047335.crashed_table WHERE etc LIKE '10001' ORDER BY id ASC LIMIT 1") }; |
557 | + |
558 | +eval { $tp->get_create_table($dbh3, 'bug_1047335', 'crashed_table') }; |
559 | +ok( |
560 | + $EVAL_ERROR, |
561 | + "get_create_table dies if SHOW CREATE TABLE failed", |
562 | +); |
563 | + |
564 | +# This might fail. Doesn't matter -- stop_sandbox will just rm -rf the folder |
565 | +eval { $dbh3->do("DROP DATABASE IF EXISTS bug_1047335") }; |
566 | + |
567 | +diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`); |
568 | + |
569 | +# ############################################################################# |
570 | # Done. |
571 | # ############################################################################# |
572 | $sb->wipe_clean($dbh) if $dbh; |
573 | ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); |
574 | + |
575 | +done_testing; |
576 | + |
577 | exit; |
578 | |
579 | === added file 't/lib/samples/bug_1047335_crashed_table.sql' |
580 | --- t/lib/samples/bug_1047335_crashed_table.sql 1970-01-01 00:00:00 +0000 |
581 | +++ t/lib/samples/bug_1047335_crashed_table.sql 2012-10-30 21:38:20 +0000 |
582 | @@ -0,0 +1,11 @@ |
583 | +DROP DATABASE IF EXISTS bug_1047335; |
584 | +CREATE DATABASE bug_1047335; |
585 | +USE bug_1047335; |
586 | +CREATE TABLE bug_1047335.crashed_table ( |
587 | + `id` int(10) unsigned NOT NULL auto_increment, |
588 | + `trx_id` int(10) unsigned default NULL, |
589 | + `etc` text, |
590 | + PRIMARY KEY (`id`), |
591 | + KEY `idx1` (`trx_id`), |
592 | + KEY `idx2` (`trx_id`, `etc`(128)) |
593 | +) ENGINE=MyISAM; |
This diff has other stuff, for MasterSlave and PXC. Can you isolate just the changes for this branch/bug?