mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-07 04:49:48 +00:00
PT-153 Added --[no]fail-on-unique-key-change param
This commit is contained in:
@@ -8941,6 +8941,7 @@ sub main {
|
||||
renamed_cols => $renamed_cols,
|
||||
Cxn => $cxn,
|
||||
TableParser => $tp,
|
||||
OptionParser => $o,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -9918,15 +9919,31 @@ sub validate_tries {
|
||||
|
||||
sub check_alter {
|
||||
my (%args) = @_;
|
||||
my @required_args = qw(alter tbl dry_run Cxn TableParser);
|
||||
my @required_args = qw(alter tbl dry_run Cxn TableParser OptionParser);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless exists $args{$arg};
|
||||
}
|
||||
my ($alter, $tbl, $dry_run, $cxn, $tp) = @args{@required_args};
|
||||
my ($alter, $tbl, $dry_run, $cxn, $tp, $o) = @args{@required_args};
|
||||
|
||||
my $ok = 1;
|
||||
|
||||
$alter = clean_alter($alter);
|
||||
my $unique_fields = get_unique_index_fields($alter);
|
||||
|
||||
if (scalar @$unique_fields && $o->get('fail-on-unique-key-change')) {
|
||||
my $msg = "You are trying to add an unique key. This is highly discouraged.\n"
|
||||
. "Please read the documentation for the --fail-on-unique-key-change parameter.\n"
|
||||
. "You can check if there are already rows that will produce duplicated indexes "
|
||||
. "by running this/these query/queries:\n\n";
|
||||
foreach my $fields (@$unique_fields) {
|
||||
my $sql = "SELECT IF(COUNT(DISTINCT " . join(", ", @$fields) . ") = COUNT(*),\n"
|
||||
. " 'Yes, the desired unique index currently contains only unique values', \n"
|
||||
. " 'No, the desired unique index contains duplicated values. There will be data loss'\n"
|
||||
. ") AS IsThereUniqueness FROM `$tbl->{db}`.`$tbl->{tbl}`;\n\n";
|
||||
$msg .= $sql;
|
||||
}
|
||||
$msg .= "Keep in mind that these queries could take a long time and consume a lot of resources\n\n";
|
||||
die ($msg);
|
||||
}
|
||||
|
||||
# ########################################################################
|
||||
# Check for DROP PRIMARY KEY.
|
||||
@@ -10035,7 +10052,7 @@ sub get_unique_index_fields {
|
||||
$clean .= $suffix;
|
||||
|
||||
my $fields = [];
|
||||
my $fields_re = qr/.*?(?:ADD|CREATE)\s*UNIQUE\s*INDEX\s*(?:\w+\s+on\s+\w+|\w+)(?:\s\w+)* \((.*?)\)/i;
|
||||
my $fields_re = qr/UNIQUE\s*INDEX\s*(?:.*?)* \((.*?)\)/i;
|
||||
|
||||
while($clean =~ /$fields_re/g) {
|
||||
push @$fields, [ split /\s*,\s*/, $1 ];
|
||||
@@ -11797,6 +11814,42 @@ only perform some safety checks and exit. This helps ensure that you have read
|
||||
documentation and understand how to use this tool. If you have not read the
|
||||
documentation, then do not specify this option.
|
||||
|
||||
=item --[no]fail-on-unique-key-change
|
||||
|
||||
default: yes
|
||||
|
||||
Force pt-online-schema-change to run even if the specified statement for --alter is
|
||||
trying to add an unique index.
|
||||
Since pt-online-schema-change uses INSERT IGNORE to copy rows to the new table, if the
|
||||
row being written produce a duplicate key, it will fail silently.
|
||||
|
||||
Example:
|
||||
|
||||
CREATE DATABASE test;
|
||||
USE test;
|
||||
CREATE TABLE `a` (
|
||||
`id` int(11) NOT NULL,
|
||||
`unique_id` varchar(32) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
insert into a values (1, "a");
|
||||
insert into a values (2, "b");
|
||||
insert into a values (3, "");
|
||||
insert into a values (4, "");
|
||||
insert into a values (5, NULL);
|
||||
insert into a values (6, NULL);
|
||||
|
||||
Using pt-osc to add an unique index on the `unique_id` field, will cause some rows to
|
||||
be lost due to the use os INSERT IGNORE to copy rows from the source table.
|
||||
For this reason, pt-osc will fail if it detects that the --alter parameter is trying
|
||||
to add an unique key and it will show an example query to run to detect if there are
|
||||
rows that will produce duplicated indexes.
|
||||
|
||||
Even if you run the query and there are no rows that will produce duplicated indexes,
|
||||
take into consideration that running INSERTs while pt-osc is running, could produce
|
||||
duplicated indexes and those rows are going to be lost without any notification.
|
||||
|
||||
=item --force
|
||||
|
||||
This options bypasses confirmation in case of using alter-foreign-keys-method = none , which might break foreign key constraints.
|
||||
|
98
t/pt-online-schema-change/pt-153.t
Normal file
98
t/pt-online-schema-change/pt-153.t
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
BEGIN {
|
||||
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
|
||||
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
|
||||
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use threads;
|
||||
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More;
|
||||
|
||||
use Data::Dumper;
|
||||
use PerconaTest;
|
||||
use Sandbox;
|
||||
use SqlModes;
|
||||
use File::Temp qw/ tempdir /;
|
||||
|
||||
plan tests => 6;
|
||||
|
||||
require "$trunk/bin/pt-online-schema-change";
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $master_dbh = $sb->get_dbh_for('master');
|
||||
my $master_dsn = 'h=127.1,P=12345,u=msandbox,p=msandbox';
|
||||
|
||||
if ( !$master_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
}
|
||||
|
||||
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
|
||||
# so we need to specify --set-vars innodb_lock_wait_timeout=3 else the
|
||||
# tool will die.
|
||||
my @args = (qw(--set-vars innodb_lock_wait_timeout=3));
|
||||
my $output;
|
||||
my $exit_status;
|
||||
my $sample = "t/pt-online-schema-change/samples/";
|
||||
|
||||
$sb->load_file('master', "$sample/pt-153.sql");
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$master_dsn,D=test,t=t1",
|
||||
'--execute',
|
||||
'--alter', "ADD UNIQUE INDEX c1 (f2, f3)",
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
isnt(
|
||||
$exit_status,
|
||||
0,
|
||||
"PT-153 Adding unique index exit status != 0.",
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/You are trying to add an unique key. This is highly discouraged./s,
|
||||
"PT-153 Adding unique index warning message.",
|
||||
);
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$master_dsn,D=test,t=t1",
|
||||
'--execute',
|
||||
'--alter', "ADD UNIQUE INDEX c1 (f2, f3), CREATE UNIQUE INDEX idx2 ON test.t1 (f3)",
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
isnt(
|
||||
$exit_status,
|
||||
0,
|
||||
"PT-153 Adding multiple unique indexes exit status != 0.",
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/You are trying to add an unique key. This is highly discouraged./s,
|
||||
"PT-153 Adding multiple unique indexes warning message.",
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/SELECT IF\(COUNT\(DISTINCT f2, f3\).*?SELECT IF\(COUNT\(DISTINCT f3\)/s,
|
||||
"PT-153 Adding multiple unique indexes -> multime example queries.",
|
||||
);
|
||||
|
||||
$master_dbh->do("DROP DATABASE IF EXISTS test");
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
$sb->wipe_clean($master_dbh);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
done_testing;
|
19
t/pt-online-schema-change/samples/pt-153.sql
Normal file
19
t/pt-online-schema-change/samples/pt-153.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
DROP DATABASE IF EXISTS test;
|
||||
CREATE DATABASE test;
|
||||
USE test;
|
||||
CREATE TABLE test.t1 (
|
||||
id int,
|
||||
f2 int,
|
||||
f3 int NULL,
|
||||
f4 int,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
INSERT INTO test.t1 VALUES
|
||||
(1,1,1,1),
|
||||
(2,1,1,1),
|
||||
(3,1,2,1),
|
||||
(4,2,NULL,2),
|
||||
(5,3,NULL,2),
|
||||
(6,4,4,4),
|
||||
(7,4,4,4);
|
Reference in New Issue
Block a user