Merge lp:~percona-toolkit-dev/percona-toolkit/pt-table-checksum-refuses-to-run-on-PXC-if-server_id-is-the-same-on-all-nodes-1217466 into lp:~percona-toolkit-dev/percona-toolkit/release-2.2.12

Proposed by Frank Cizmich
Status: Merged
Approved by: Daniel Nichter
Approved revision: 626
Merged at revision: 635
Proposed branch: lp:~percona-toolkit-dev/percona-toolkit/pt-table-checksum-refuses-to-run-on-PXC-if-server_id-is-the-same-on-all-nodes-1217466
Merge into: lp:~percona-toolkit-dev/percona-toolkit/release-2.2.12
Diff against target: 752 lines (+321/-78)
10 files modified
bin/pt-config-diff (+22/-3)
bin/pt-deadlock-logger (+22/-3)
bin/pt-fk-error-logger (+22/-3)
bin/pt-kill (+22/-3)
bin/pt-online-schema-change (+43/-6)
bin/pt-table-checksum (+44/-6)
bin/pt-upgrade (+22/-3)
lib/Cxn.pm (+19/-2)
lib/Percona/XtraDB/Cluster.pm (+23/-2)
t/pt-table-checksum/pxc.t (+82/-47)
To merge this branch: bzr merge lp:~percona-toolkit-dev/percona-toolkit/pt-table-checksum-refuses-to-run-on-PXC-if-server_id-is-the-same-on-all-nodes-1217466
Reviewer Review Type Date Requested Status
Daniel Nichter Approve
Review via email: mp+239451@code.launchpad.net

Description of the change

problem:
Sometimes PXC setups use the same ID for all nodes ( no consensus yet if this is "right" or "wrong" )
This made pt-table-checksum discard nodes with the same ID although they were different nodes.

fix:
Changed remove_duplicate_cxns() function in Cxn and Percona::XtraDB::Cluster to use wsrep_node_incoming_address as a unique identifier if it's a cluster node.
Also changed pt-table-checksum to populate the %seen_ids param accordingly before passing it to the function.

caveat:
the seen_ids parameter has to be populated carefully using this criteria. At this point only pt-table-checksum uses it.
Maybe a cleaner way would be to create a get_unique_id function in Cxn

To post a comment you must log in.
Revision history for this message
Daniel Nichter (daniel-nichter) wrote :

I added on comment. If you agree, then great, feel free to change code. Otherwise, is good.

review: Approve
627. By Frank Cizmich

minor style change

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/pt-config-diff'
2--- bin/pt-config-diff 2014-09-25 13:48:22 +0000
3+++ bin/pt-config-diff 2014-11-05 22:22:52 +0000
4@@ -2295,7 +2295,7 @@
5 set => $args{set},
6 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
7 dbh_set => 0,
8- ask_pass => $o->get('ask-pass'),
9+ ask_pass => $args{ask_pass},
10 DSNParser => $dp,
11 is_cluster_node => undef,
12 parent => $args{parent},
13@@ -2306,7 +2306,7 @@
14
15 sub connect {
16 my ( $self, %opts ) = @_;
17- my $dsn = $self->{dsn};
18+ my $dsn = $opts{dsn} || $self->{dsn};
19 my $dp = $self->{DSNParser};
20
21 my $dbh = $self->{dbh};
22@@ -2325,6 +2325,13 @@
23 }
24
25 $dbh = $self->set_dbh($dbh);
26+ if ( $opts{dsn} ) {
27+ $self->{dsn} = $dsn;
28+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
29+ || $dp->as_string($dsn, [qw(F)])
30+ || '';
31+
32+ }
33 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
34 return $dbh;
35 }
36@@ -2386,6 +2393,17 @@
37 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
38 }
39
40+sub is_cluster_node {
41+ my ($self, $cxn) = @_;
42+
43+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
44+ PTDEBUG && _d($cxn->name, $sql);
45+ my $row = $cxn->dbh->selectrow_arrayref($sql);
46+ PTDEBUG && _d(Dumper($row));
47+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
48+
49+}
50+
51 sub remove_duplicate_cxns {
52 my ($self, %args) = @_;
53 my @cxns = @{$args{cxns}};
54@@ -2395,7 +2413,8 @@
55
56 for my $cxn ( @cxns ) {
57 my $dbh = $cxn->dbh();
58- my $sql = q{SELECT @@server_id};
59+
60+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
61 PTDEBUG && _d($sql);
62 my ($id) = $dbh->selectrow_array($sql);
63 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
64
65=== modified file 'bin/pt-deadlock-logger'
66--- bin/pt-deadlock-logger 2014-09-25 13:48:22 +0000
67+++ bin/pt-deadlock-logger 2014-11-05 22:22:52 +0000
68@@ -2639,7 +2639,7 @@
69 set => $args{set},
70 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
71 dbh_set => 0,
72- ask_pass => $o->get('ask-pass'),
73+ ask_pass => $args{ask_pass},
74 DSNParser => $dp,
75 is_cluster_node => undef,
76 parent => $args{parent},
77@@ -2650,7 +2650,7 @@
78
79 sub connect {
80 my ( $self, %opts ) = @_;
81- my $dsn = $self->{dsn};
82+ my $dsn = $opts{dsn} || $self->{dsn};
83 my $dp = $self->{DSNParser};
84
85 my $dbh = $self->{dbh};
86@@ -2669,6 +2669,13 @@
87 }
88
89 $dbh = $self->set_dbh($dbh);
90+ if ( $opts{dsn} ) {
91+ $self->{dsn} = $dsn;
92+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
93+ || $dp->as_string($dsn, [qw(F)])
94+ || '';
95+
96+ }
97 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
98 return $dbh;
99 }
100@@ -2730,6 +2737,17 @@
101 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
102 }
103
104+sub is_cluster_node {
105+ my ($self, $cxn) = @_;
106+
107+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
108+ PTDEBUG && _d($cxn->name, $sql);
109+ my $row = $cxn->dbh->selectrow_arrayref($sql);
110+ PTDEBUG && _d(Dumper($row));
111+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
112+
113+}
114+
115 sub remove_duplicate_cxns {
116 my ($self, %args) = @_;
117 my @cxns = @{$args{cxns}};
118@@ -2739,7 +2757,8 @@
119
120 for my $cxn ( @cxns ) {
121 my $dbh = $cxn->dbh();
122- my $sql = q{SELECT @@server_id};
123+
124+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
125 PTDEBUG && _d($sql);
126 my ($id) = $dbh->selectrow_array($sql);
127 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
128
129=== modified file 'bin/pt-fk-error-logger'
130--- bin/pt-fk-error-logger 2014-09-25 13:48:22 +0000
131+++ bin/pt-fk-error-logger 2014-11-05 22:22:52 +0000
132@@ -1791,7 +1791,7 @@
133 set => $args{set},
134 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
135 dbh_set => 0,
136- ask_pass => $o->get('ask-pass'),
137+ ask_pass => $args{ask_pass},
138 DSNParser => $dp,
139 is_cluster_node => undef,
140 parent => $args{parent},
141@@ -1802,7 +1802,7 @@
142
143 sub connect {
144 my ( $self, %opts ) = @_;
145- my $dsn = $self->{dsn};
146+ my $dsn = $opts{dsn} || $self->{dsn};
147 my $dp = $self->{DSNParser};
148
149 my $dbh = $self->{dbh};
150@@ -1821,6 +1821,13 @@
151 }
152
153 $dbh = $self->set_dbh($dbh);
154+ if ( $opts{dsn} ) {
155+ $self->{dsn} = $dsn;
156+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
157+ || $dp->as_string($dsn, [qw(F)])
158+ || '';
159+
160+ }
161 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
162 return $dbh;
163 }
164@@ -1882,6 +1889,17 @@
165 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
166 }
167
168+sub is_cluster_node {
169+ my ($self, $cxn) = @_;
170+
171+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
172+ PTDEBUG && _d($cxn->name, $sql);
173+ my $row = $cxn->dbh->selectrow_arrayref($sql);
174+ PTDEBUG && _d(Dumper($row));
175+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
176+
177+}
178+
179 sub remove_duplicate_cxns {
180 my ($self, %args) = @_;
181 my @cxns = @{$args{cxns}};
182@@ -1891,7 +1909,8 @@
183
184 for my $cxn ( @cxns ) {
185 my $dbh = $cxn->dbh();
186- my $sql = q{SELECT @@server_id};
187+
188+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
189 PTDEBUG && _d($sql);
190 my ($id) = $dbh->selectrow_array($sql);
191 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
192
193=== modified file 'bin/pt-kill'
194--- bin/pt-kill 2014-09-25 13:48:22 +0000
195+++ bin/pt-kill 2014-11-05 22:22:52 +0000
196@@ -5158,7 +5158,7 @@
197 set => $args{set},
198 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
199 dbh_set => 0,
200- ask_pass => $o->get('ask-pass'),
201+ ask_pass => $args{ask_pass},
202 DSNParser => $dp,
203 is_cluster_node => undef,
204 parent => $args{parent},
205@@ -5169,7 +5169,7 @@
206
207 sub connect {
208 my ( $self, %opts ) = @_;
209- my $dsn = $self->{dsn};
210+ my $dsn = $opts{dsn} || $self->{dsn};
211 my $dp = $self->{DSNParser};
212
213 my $dbh = $self->{dbh};
214@@ -5188,6 +5188,13 @@
215 }
216
217 $dbh = $self->set_dbh($dbh);
218+ if ( $opts{dsn} ) {
219+ $self->{dsn} = $dsn;
220+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
221+ || $dp->as_string($dsn, [qw(F)])
222+ || '';
223+
224+ }
225 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
226 return $dbh;
227 }
228@@ -5249,6 +5256,17 @@
229 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
230 }
231
232+sub is_cluster_node {
233+ my ($self, $cxn) = @_;
234+
235+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
236+ PTDEBUG && _d($cxn->name, $sql);
237+ my $row = $cxn->dbh->selectrow_arrayref($sql);
238+ PTDEBUG && _d(Dumper($row));
239+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
240+
241+}
242+
243 sub remove_duplicate_cxns {
244 my ($self, %args) = @_;
245 my @cxns = @{$args{cxns}};
246@@ -5258,7 +5276,8 @@
247
248 for my $cxn ( @cxns ) {
249 my $dbh = $cxn->dbh();
250- my $sql = q{SELECT @@server_id};
251+
252+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
253 PTDEBUG && _d($sql);
254 my ($id) = $dbh->selectrow_array($sql);
255 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
256
257=== modified file 'bin/pt-online-schema-change'
258--- bin/pt-online-schema-change 2014-09-25 13:48:22 +0000
259+++ bin/pt-online-schema-change 2014-11-05 22:22:52 +0000
260@@ -3755,7 +3755,7 @@
261 set => $args{set},
262 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
263 dbh_set => 0,
264- ask_pass => $o->get('ask-pass'),
265+ ask_pass => $args{ask_pass},
266 DSNParser => $dp,
267 is_cluster_node => undef,
268 parent => $args{parent},
269@@ -3766,12 +3766,12 @@
270
271 sub connect {
272 my ( $self, %opts ) = @_;
273- my $dsn = $self->{dsn};
274+ my $dsn = $opts{dsn} || $self->{dsn};
275 my $dp = $self->{DSNParser};
276
277 my $dbh = $self->{dbh};
278 if ( !$dbh || !$dbh->ping() ) {
279- if ( $self->{ask_pass} && !$self->{asked_for_pass} && !defined $dsn->{p}) {
280+ if ( $self->{ask_pass} && !$self->{asked_for_pass} ) {
281 $dsn->{p} = OptionParser::prompt_noecho("Enter MySQL password: ");
282 $self->{asked_for_pass} = 1;
283 }
284@@ -3785,6 +3785,13 @@
285 }
286
287 $dbh = $self->set_dbh($dbh);
288+ if ( $opts{dsn} ) {
289+ $self->{dsn} = $dsn;
290+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
291+ || $dp->as_string($dsn, [qw(F)])
292+ || '';
293+
294+ }
295 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
296 return $dbh;
297 }
298@@ -3846,6 +3853,17 @@
299 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
300 }
301
302+sub is_cluster_node {
303+ my ($self, $cxn) = @_;
304+
305+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
306+ PTDEBUG && _d($cxn->name, $sql);
307+ my $row = $cxn->dbh->selectrow_arrayref($sql);
308+ PTDEBUG && _d(Dumper($row));
309+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
310+
311+}
312+
313 sub remove_duplicate_cxns {
314 my ($self, %args) = @_;
315 my @cxns = @{$args{cxns}};
316@@ -3855,7 +3873,8 @@
317
318 for my $cxn ( @cxns ) {
319 my $dbh = $cxn->dbh();
320- my $sql = q{SELECT @@server_id};
321+
322+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
323 PTDEBUG && _d($sql);
324 my ($id) = $dbh->selectrow_array($sql);
325 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
326@@ -7638,8 +7657,26 @@
327 sub remove_duplicate_cxns {
328 my ($self, %args) = @_;
329 my @cxns = @{$args{cxns}};
330- my $seen_ids = $args{seen_ids};
331- return Cxn->remove_duplicate_cxns(%args);
332+ my $seen_ids = $args{seen_ids} || {};
333+ PTDEBUG && _d("Removing duplicates nodes from ", join(" ", map { $_->name } @cxns));
334+ my @trimmed_cxns;
335+
336+ for my $cxn ( @cxns ) {
337+ my $dbh = $cxn->dbh();
338+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
339+ PTDEBUG && _d($sql);
340+ my ($id) = $dbh->selectrow_array($sql);
341+ PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
342+
343+ if ( ! $seen_ids->{$id}++ ) {
344+ push @trimmed_cxns, $cxn
345+ }
346+ else {
347+ PTDEBUG && _d("Removing ", $cxn->name,
348+ ", ID ", $id, ", because we've already seen it");
349+ }
350+ }
351+ return \@trimmed_cxns;
352 }
353
354 sub same_cluster {
355
356=== modified file 'bin/pt-table-checksum'
357--- bin/pt-table-checksum 2014-09-25 13:48:22 +0000
358+++ bin/pt-table-checksum 2014-11-05 22:22:52 +0000
359@@ -3533,7 +3533,7 @@
360 set => $args{set},
361 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
362 dbh_set => 0,
363- ask_pass => $o->get('ask-pass'),
364+ ask_pass => $args{ask_pass},
365 DSNParser => $dp,
366 is_cluster_node => undef,
367 parent => $args{parent},
368@@ -3544,7 +3544,7 @@
369
370 sub connect {
371 my ( $self, %opts ) = @_;
372- my $dsn = $self->{dsn};
373+ my $dsn = $opts{dsn} || $self->{dsn};
374 my $dp = $self->{DSNParser};
375
376 my $dbh = $self->{dbh};
377@@ -3563,6 +3563,13 @@
378 }
379
380 $dbh = $self->set_dbh($dbh);
381+ if ( $opts{dsn} ) {
382+ $self->{dsn} = $dsn;
383+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
384+ || $dp->as_string($dsn, [qw(F)])
385+ || '';
386+
387+ }
388 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
389 return $dbh;
390 }
391@@ -3624,6 +3631,17 @@
392 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
393 }
394
395+sub is_cluster_node {
396+ my ($self, $cxn) = @_;
397+
398+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
399+ PTDEBUG && _d($cxn->name, $sql);
400+ my $row = $cxn->dbh->selectrow_arrayref($sql);
401+ PTDEBUG && _d(Dumper($row));
402+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
403+
404+}
405+
406 sub remove_duplicate_cxns {
407 my ($self, %args) = @_;
408 my @cxns = @{$args{cxns}};
409@@ -3633,7 +3651,8 @@
410
411 for my $cxn ( @cxns ) {
412 my $dbh = $cxn->dbh();
413- my $sql = q{SELECT @@server_id};
414+
415+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
416 PTDEBUG && _d($sql);
417 my ($id) = $dbh->selectrow_array($sql);
418 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
419@@ -3788,8 +3807,26 @@
420 sub remove_duplicate_cxns {
421 my ($self, %args) = @_;
422 my @cxns = @{$args{cxns}};
423- my $seen_ids = $args{seen_ids};
424- return Cxn->remove_duplicate_cxns(%args);
425+ my $seen_ids = $args{seen_ids} || {};
426+ PTDEBUG && _d("Removing duplicates nodes from ", join(" ", map { $_->name } @cxns));
427+ my @trimmed_cxns;
428+
429+ for my $cxn ( @cxns ) {
430+ my $dbh = $cxn->dbh();
431+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
432+ PTDEBUG && _d($sql);
433+ my ($id) = $dbh->selectrow_array($sql);
434+ PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
435+
436+ if ( ! $seen_ids->{$id}++ ) {
437+ push @trimmed_cxns, $cxn
438+ }
439+ else {
440+ PTDEBUG && _d("Removing ", $cxn->name,
441+ ", ID ", $id, ", because we've already seen it");
442+ }
443+ }
444+ return \@trimmed_cxns;
445 }
446
447 sub same_cluster {
448@@ -9286,7 +9323,8 @@
449 my %seen_ids;
450 for my $cxn ($master_cxn, @$slaves) {
451 my $dbh = $cxn->dbh();
452- my $sql = q{SELECT @@server_id};
453+ # if it's a cluster node we use its incoming address as id ( see https://bugs.launchpad.net/percona-toolkit/+bug/1217466 )
454+ my $sql = $cluster->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
455 PTDEBUG && _d($cxn, $dbh, $sql);
456 my ($id) = $dbh->selectrow_array($sql);
457 $seen_ids{$id}++;
458
459=== modified file 'bin/pt-upgrade'
460--- bin/pt-upgrade 2014-09-25 13:48:22 +0000
461+++ bin/pt-upgrade 2014-11-05 22:22:52 +0000
462@@ -2464,7 +2464,7 @@
463 set => $args{set},
464 NAME_lc => defined($args{NAME_lc}) ? $args{NAME_lc} : 1,
465 dbh_set => 0,
466- ask_pass => $o->get('ask-pass'),
467+ ask_pass => $args{ask_pass},
468 DSNParser => $dp,
469 is_cluster_node => undef,
470 parent => $args{parent},
471@@ -2475,7 +2475,7 @@
472
473 sub connect {
474 my ( $self, %opts ) = @_;
475- my $dsn = $self->{dsn};
476+ my $dsn = $opts{dsn} || $self->{dsn};
477 my $dp = $self->{DSNParser};
478
479 my $dbh = $self->{dbh};
480@@ -2494,6 +2494,13 @@
481 }
482
483 $dbh = $self->set_dbh($dbh);
484+ if ( $opts{dsn} ) {
485+ $self->{dsn} = $dsn;
486+ $self->{dsn_name} = $dp->as_string($dsn, [qw(h P S)])
487+ || $dp->as_string($dsn, [qw(F)])
488+ || '';
489+
490+ }
491 PTDEBUG && _d($dbh, 'Connected dbh to', $self->{hostname},$self->{dsn_name});
492 return $dbh;
493 }
494@@ -2555,6 +2562,17 @@
495 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
496 }
497
498+sub is_cluster_node {
499+ my ($self, $cxn) = @_;
500+
501+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
502+ PTDEBUG && _d($cxn->name, $sql);
503+ my $row = $cxn->dbh->selectrow_arrayref($sql);
504+ PTDEBUG && _d(Dumper($row));
505+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
506+
507+}
508+
509 sub remove_duplicate_cxns {
510 my ($self, %args) = @_;
511 my @cxns = @{$args{cxns}};
512@@ -2564,7 +2582,8 @@
513
514 for my $cxn ( @cxns ) {
515 my $dbh = $cxn->dbh();
516- my $sql = q{SELECT @@server_id};
517+
518+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
519 PTDEBUG && _d($sql);
520 my ($id) = $dbh->selectrow_array($sql);
521 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
522
523=== modified file 'lib/Cxn.pm'
524--- lib/Cxn.pm 2013-12-05 00:14:17 +0000
525+++ lib/Cxn.pm 2014-11-05 22:22:52 +0000
526@@ -226,6 +226,19 @@
527 return $self->{hostname} || $self->{dsn_name} || 'unknown host';
528 }
529
530+# This is used to help remove_duplicate_cxns detect cluster nodes
531+# (which often have unreliable server_id's)
532+sub is_cluster_node {
533+ my ($self, $cxn) = @_;
534+
535+ my $sql = "SHOW VARIABLES LIKE 'wsrep\_on'";
536+ PTDEBUG && _d($cxn->name, $sql);
537+ my $row = $cxn->dbh->selectrow_arrayref($sql);
538+ PTDEBUG && _d(Dumper($row));
539+ return $row && $row->[1] && ($row->[1] eq 'ON' || $row->[1] eq '1') ? 1 : 0;
540+
541+}
542+
543 # There's two reasons why there might be dupes:
544 # If the "master" is a cluster node, then a DSN table might have been
545 # used, and it may have all nodes' DSNs so the user can run the tool
546@@ -233,7 +246,7 @@
547 # on the command line.
548 # On the other hand, maybe find_cluster_nodes worked, in which case
549 # we definitely have a dupe for the master cxn, but we may also have a
550-# dupe for every other node if this was unsed in conjunction with a
551+# dupe for every other node if this was used in conjunction with a
552 # DSN table.
553 # So try to detect and remove those.
554 sub remove_duplicate_cxns {
555@@ -245,7 +258,11 @@
556
557 for my $cxn ( @cxns ) {
558 my $dbh = $cxn->dbh();
559- my $sql = q{SELECT @@server_id};
560+
561+ # Very often cluster nodes are configured with matching server_id's
562+ # So in that case we'll use its incoming address as its unique identifier
563+ # Note: this relies on "seen_ids" being populated using the same strategy
564+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
565 PTDEBUG && _d($sql);
566 my ($id) = $dbh->selectrow_array($sql);
567 PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
568
569=== modified file 'lib/Percona/XtraDB/Cluster.pm'
570--- lib/Percona/XtraDB/Cluster.pm 2013-04-16 20:40:32 +0000
571+++ lib/Percona/XtraDB/Cluster.pm 2014-11-05 22:22:52 +0000
572@@ -132,8 +132,29 @@
573 sub remove_duplicate_cxns {
574 my ($self, %args) = @_;
575 my @cxns = @{$args{cxns}};
576- my $seen_ids = $args{seen_ids};
577- return Cxn->remove_duplicate_cxns(%args);
578+ my $seen_ids = $args{seen_ids} || {};
579+ PTDEBUG && _d("Removing duplicates nodes from ", join(" ", map { $_->name } @cxns));
580+ my @trimmed_cxns;
581+
582+ for my $cxn ( @cxns ) {
583+ my $dbh = $cxn->dbh();
584+ # Very often cluster nodes are configured with matching server_id's
585+ # So in that case we'll use its incoming address as its unique identifier
586+ # Note: This relies on "seen_ids" being populated using the same strategy
587+ my $sql = $self->is_cluster_node($cxn) ? q{SELECT @@wsrep_node_incoming_address} : q{SELECT @@server_id};
588+ PTDEBUG && _d($sql);
589+ my ($id) = $dbh->selectrow_array($sql);
590+ PTDEBUG && _d('Server ID for ', $cxn->name, ': ', $id);
591+
592+ if ( ! $seen_ids->{$id}++ ) {
593+ push @trimmed_cxns, $cxn
594+ }
595+ else {
596+ PTDEBUG && _d("Removing ", $cxn->name,
597+ ", ID ", $id, ", because we've already seen it");
598+ }
599+ }
600+ return \@trimmed_cxns;
601 }
602
603 sub same_cluster {
604
605=== modified file 't/pt-table-checksum/pxc.t'
606--- t/pt-table-checksum/pxc.t 2013-04-12 15:58:10 +0000
607+++ t/pt-table-checksum/pxc.t 2014-11-05 22:22:52 +0000
608@@ -144,54 +144,89 @@
609 "Node3 not changed"
610 );
611
612-for my $args (
613- ["using recusion-method=dsn", '--recursion-method', "dsn=$node1_dsn,D=dsns,t=dsns"],
614- ["using recursion-method=cluster", '--recursion-method', 'cluster']
615- )
616-{
617- my $test = shift @$args;
618-
619- $output = output(
620- sub { pt_table_checksum::main(@args,
621- @$args)
622- },
623- stderr => 1,
624- );
625-
626- is(
627- PerconaTest::count_checksum_results($output, 'errors'),
628- 0,
629- "1 diff: no errors ($test)"
630- );
631-
632- is(
633- PerconaTest::count_checksum_results($output, 'skipped'),
634- 0,
635- "1 diff: no skips ($test)"
636- );
637-
638- is(
639- PerconaTest::count_checksum_results($output, 'diffs'),
640- 1,
641- "1 diff: 1 diff ($test)"
642- ) or diag($output);
643-
644- # 11-17T13:02:54 0 1 26 1 0 0.021 test.t
645- like(
646- $output,
647- qr/^\S+\s+ # ts
648- 0\s+ # errors
649- 1\s+ # diffs
650- 26\s+ # rows
651- \d+\s+ # chunks
652- 0\s+ # skipped
653- \S+\s+ # time
654- test.t$ # table
655- /xm,
656- "1 diff: it's in test.t ($test)"
657- );
658+sub test_recursion_methods {
659+ my $same_ids = shift;
660+
661+ my ($orig_id_1, $orig_id_2, $orig_id_3);
662+
663+ if ($same_ids) {
664+ # save original values
665+ my $sql = 'SELECT @@server_id';
666+ ($orig_id_1) = $node1->selectrow_array($sql);
667+ ($orig_id_2) = $node2->selectrow_array($sql);
668+ ($orig_id_3) = $node3->selectrow_array($sql);
669+ # set server_id value to 1 on all nodes
670+ $sql = 'SET GLOBAL server_id = 1';
671+ $node1->do($sql);
672+ $node2->do($sql);
673+ $node3->do($sql);
674+ }
675+
676+ for my $args (
677+ ["using recusion-method=dsn", '--recursion-method', "dsn=$node1_dsn,D=dsns,t=dsns"],
678+ ["using recursion-method=cluster", '--recursion-method', 'cluster']
679+ )
680+ {
681+ my $test = shift @$args;
682+ $test = $same_ids ? $test.' - Nodes with different ids' : $test.' - Nodes with same ids';
683+
684+ $output = output(
685+ sub { pt_table_checksum::main(@args,
686+ @$args)
687+ },
688+ stderr => 1,
689+ );
690+
691+ is(
692+ PerconaTest::count_checksum_results($output, 'errors'),
693+ 0,
694+ "1 diff: no errors ($test)"
695+ );
696+
697+ is(
698+ PerconaTest::count_checksum_results($output, 'skipped'),
699+ 0,
700+ "1 diff: no skips ($test)"
701+ );
702+
703+ is(
704+ PerconaTest::count_checksum_results($output, 'diffs'),
705+ 1,
706+ "1 diff: 1 diff ($test)"
707+ ) or diag($output);
708+
709+ # 11-17T13:02:54 0 1 26 1 0 0.021 test.t
710+ like(
711+ $output,
712+ qr/^\S+\s+ # ts
713+ 0\s+ # errors
714+ 1\s+ # diffs
715+ 26\s+ # rows
716+ \d+\s+ # chunks
717+ 0\s+ # skipped
718+ \S+\s+ # time
719+ test.t$ # table
720+ /xm,
721+ "1 diff: it's in test.t ($test)"
722+ );
723+ }
724+
725+ if ($same_ids) {
726+ # reset server_id's to original values
727+ $node1->do("SET GLOBAL server_id = $orig_id_1");
728+ $node2->do("SET GLOBAL server_id = $orig_id_2");
729+ $node3->do("SET GLOBAL server_id = $orig_id_3");
730+ }
731+
732 }
733
734+# test recursion methods
735+test_recursion_methods(0);
736+
737+# test recursion methods when all nodes have the same id
738+test_recursion_methods(1);
739+
740+
741 # #############################################################################
742 # cluster, node1 -> slave, run on node1
743 # #############################################################################
744@@ -232,7 +267,7 @@
745 # Wait for the slave to apply the binlogs from node1 (its master).
746 # Then change it so it's not consistent.
747 PerconaTest::wait_for_table($slave_dbh, 'test.t');
748- $sb->wait_for_slaves('cslave1');
749+ $sb->wait_for_slaves(master=> 'node1', slave => 'cslave1');
750 $slave_dbh->do("update test.t set c='zebra' where c='z'");
751
752 $output = output(

Subscribers

People subscribed via source and target branches

to all changes: