Merge lp:~sergei.glushchenko/percona-server/56-expand_fast_index_creation into lp:percona-server/5.6

Proposed by Sergei Glushchenko
Status: Merged
Approved by: Stewart Smith
Approved revision: no longer in the source branch.
Merged at revision: 311
Proposed branch: lp:~sergei.glushchenko/percona-server/56-expand_fast_index_creation
Merge into: lp:percona-server/5.6
Diff against target: 1888 lines (+1469/-6)
24 files modified
Percona-Server/client/client_priv.h (+1/-0)
Percona-Server/client/mysqldump.c (+310/-3)
Percona-Server/mysql-test/r/mysqld--help-notwin.result (+5/-0)
Percona-Server/mysql-test/r/mysqld--help-win.result (+5/-0)
Percona-Server/mysql-test/r/percona_expand_fast_index_creation.result (+78/-0)
Percona-Server/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result (+443/-0)
Percona-Server/mysql-test/suite/innodb/r/percona_bug_999147.result (+17/-0)
Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147-master.opt (+1/-0)
Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147.test (+29/-0)
Percona-Server/mysql-test/suite/sys_vars/r/expand_fast_index_creation_basic.result (+6/-0)
Percona-Server/mysql-test/suite/sys_vars/t/expand_fast_index_creation_basic.test (+2/-0)
Percona-Server/mysql-test/t/percona_expand_fast_index_creation.test (+77/-0)
Percona-Server/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test (+227/-0)
Percona-Server/sql/handler.cc (+4/-2)
Percona-Server/sql/mysqld.cc (+3/-1)
Percona-Server/sql/mysqld.h (+1/-0)
Percona-Server/sql/sql_alter.cc (+4/-0)
Percona-Server/sql/sql_alter.h (+6/-0)
Percona-Server/sql/sql_class.h (+1/-0)
Percona-Server/sql/sql_table.cc (+215/-0)
Percona-Server/sql/sys_vars.cc (+8/-0)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+14/-0)
Percona-Server/storage/innobase/handler/handler0alter.cc (+2/-0)
Percona-Server/storage/innobase/include/ha_prototypes.h (+10/-0)
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-server/56-expand_fast_index_creation
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Needs Fixing
Stewart Smith (community) Needs Fixing
Alexey Kopytov (community) Approve
Review via email: mp+139747@code.launchpad.net

Description of the change

The port of expand fast index creation patch.

The only significant change is that online/inplace ALTER TABLE API was introduced in MySQL 5.6.

Drop and create keys on temporary table is performed as following.
Create Alter_info which describe table changes. As fields of the
table are not changed, populate clreate_list with field definitions
using field==orig_field. Create Alter_inplace_info describing
alter operations to be performed. Fill index_drop_buffer or
index_add_buffer respectively. Set ADD_INDEX/DROP_INDEX handler flag.
Check that operation could be performed online by calling
check_if_supported_inplace_alter. Perform alter operation by calling
ha_prepare_inplace_alter_table,ha_inplace_alter_table,
ha_commit_inplace_alter_table.

http://jenkins.percona.com/view/PS%205.6/job/percona-server-5.6-param/14/

To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

I forgot to add testcases

Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :
Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve
Revision history for this message
Stewart Smith (stewart) wrote :

http://jenkins.percona.com/job/merge-PS-5.6-staging/3/BUILD_TYPE=release,Host=ubuntu-lucid-64bit/testReport/junit/%28root%29/main/percona_expand_fast_index_creation/ (and others)

CURRENT_TEST: main.percona_expand_fast_index_creation
--- /mnt/workspace/merge-PS-5.6-staging/BUILD_TYPE/release/Host/ubuntu-lucid-64bit/Percona-Server/mysql-test/r/percona_expand_fast_index_creation.result 2013-01-25 03:39:48.000000000 +0300
+++ /mnt/workspace/merge-PS-5.6-staging/BUILD_TYPE/release/Host/ubuntu-lucid-64bit/Percona-Server/mysql-test/r/percona_expand_fast_index_creation.reject 2013-01-25 04:07:36.000000000 +0300
@@ -36,8 +36,12 @@
 k4 2 3 d 2
 PRIMARY 3 1 a 0
 SET profiling=1;
+Warnings:
+Warning 1287 '@@profiling' is deprecated and will be removed in a future release.
 ALTER TABLE t MODIFY COLUMN z VARCHAR(2);
 SET profiling=0;
+Warnings:
+Warning 1287 '@@profiling' is deprecated and will be removed in a future release.
 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROFILING
 WHERE STATE = 'restoring secondary keys' AND
 QUERY_ID = (SELECT MAX(QUERY_ID) FROM INFORMATION_SCHEMA.PROFILING);

review: Needs Fixing
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

http://jenkins.percona.com/view/PS%205.6/job/percona-server-5.6-param/27/

* @@profiling, SHOW PROFILE and I_S.PROFILING were
deprecated in later MySQL 5.6 version. it led to
test failure
* solution is to use performance_schema.events_stages_long
* also instead of thd_proc_info, THD_STAGE_INFO has been
used
* and new event 'stage/sql/restoring secondary keys' has
been introduced

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

This has caused bug 1133926.

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Percona-Server/client/client_priv.h'
2--- Percona-Server/client/client_priv.h 2012-12-04 08:24:59 +0000
3+++ Percona-Server/client/client_priv.h 2013-01-25 11:48:25 +0000
4@@ -100,6 +100,7 @@
5 OPT_CONFIG_ALL,
6 OPT_SERVER_PUBLIC_KEY,
7 OPT_ENABLE_CLEARTEXT_PLUGIN,
8+ OPT_INNODB_OPTIMIZE_KEYS,
9 OPT_MAX_CLIENT_OPTION
10 };
11
12
13=== modified file 'Percona-Server/client/mysqldump.c'
14--- Percona-Server/client/mysqldump.c 2012-10-16 06:21:51 +0000
15+++ Percona-Server/client/mysqldump.c 2013-01-25 11:48:25 +0000
16@@ -47,6 +47,7 @@
17 #include <m_ctype.h>
18 #include <hash.h>
19 #include <stdarg.h>
20+#include <my_list.h>
21
22 #include "client_priv.h"
23 #include "my_default.h"
24@@ -84,6 +85,13 @@
25 #define IGNORE_DATA 0x01 /* don't dump data for this table */
26 #define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
27
28+typedef enum {
29+ KEY_TYPE_NONE,
30+ KEY_TYPE_PRIMARY,
31+ KEY_TYPE_UNIQUE,
32+ KEY_TYPE_NON_UNIQUE
33+} key_type_t;
34+
35 /* general_log or slow_log tables under mysql database */
36 static inline my_bool general_log_or_slow_log_tables(const char *db,
37 const char *table)
38@@ -155,6 +163,8 @@
39 static uint opt_protocol= 0;
40 static char *opt_plugin_dir= 0, *opt_default_auth= 0;
41
42+static my_bool opt_innodb_optimize_keys= FALSE;
43+
44 /*
45 Dynamic_string wrapper functions. In this file use these
46 wrappers, they will terminate the process if there is
47@@ -200,6 +210,8 @@
48
49 HASH ignore_table;
50
51+LIST *skipped_keys_list;
52+
53 static struct my_option my_long_options[] =
54 {
55 {"all-databases", 'A',
56@@ -369,6 +381,11 @@
57 "in dump produced with --dump-slave.", &opt_include_master_host_port,
58 &opt_include_master_host_port, 0, GET_BOOL, NO_ARG,
59 0, 0, 0, 0, 0, 0},
60+ {"innodb-optimize-keys", OPT_INNODB_OPTIMIZE_KEYS,
61+ "Use InnoDB fast index creation by creating secondary indexes after "
62+ "dumping the data.",
63+ &opt_innodb_optimize_keys, &opt_innodb_optimize_keys, 0, GET_BOOL, NO_ARG,
64+ 0, 0, 0, 0, 0, 0},
65 {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
66 &opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
67 0, 0},
68@@ -2447,6 +2464,256 @@
69 }
70
71 /*
72+ Parse the specified key definition string and check if the key contains an
73+ AUTO_INCREMENT column as the first key part. We only check for the first key
74+ part, because unlike MyISAM, InnoDB does not allow the AUTO_INCREMENT column
75+ as a secondary key column, i.e. the AUTO_INCREMENT column would not be
76+ considered indexed for such key specification.
77+*/
78+static my_bool contains_autoinc_column(const char *autoinc_column,
79+ const char *keydef,
80+ key_type_t type)
81+{
82+ char *from, *to;
83+ uint idnum;
84+
85+ DBUG_ASSERT(type != KEY_TYPE_NONE);
86+
87+ if (autoinc_column == NULL || !(from= strchr(keydef, '`')))
88+ return FALSE;
89+
90+ to= from;
91+ idnum= 0;
92+
93+ while ((to= strchr(to + 1, '`')))
94+ {
95+ /*
96+ Double backticks represent a backtick in identifier, rather than a quote
97+ character.
98+ */
99+ if (to[1] == '`')
100+ {
101+ to++;
102+ continue;
103+ }
104+
105+ if (to <= from + 1)
106+ break; /* Broken key definition */
107+
108+ idnum++;
109+
110+ /*
111+ Skip the check if it's the first identifier and we are processing a
112+ secondary key.
113+ */
114+ if ((type == KEY_TYPE_PRIMARY || idnum != 1) &&
115+ !strncmp(autoinc_column, from + 1, to - from - 1))
116+ return TRUE;
117+
118+ /*
119+ Check only the first (for PRIMARY KEY) or the second (for secondary keys)
120+ quoted identifier.
121+ */
122+ if ((idnum == 1 + test(type != KEY_TYPE_PRIMARY)) ||
123+ !(from= strchr(to + 1, '`')))
124+ break;
125+
126+ to= from;
127+ }
128+
129+ return FALSE;
130+}
131+
132+
133+/*
134+ Remove secondary/foreign key definitions from a given SHOW CREATE TABLE string
135+ and store them into a temporary list to be used later.
136+
137+ SYNOPSIS
138+ skip_secondary_keys()
139+ create_str SHOW CREATE TABLE output
140+ has_pk TRUE, if the table has PRIMARY KEY
141+ (or UNIQUE key on non-nullable columns)
142+
143+
144+ DESCRIPTION
145+
146+ Stores all lines starting with "KEY" or "UNIQUE KEY"
147+ into skipped_keys_list and removes them from the input string.
148+ Ignoring FOREIGN KEYS constraints when creating the table is ok, because
149+ mysqldump sets foreign_key_checks to 0 anyway.
150+*/
151+
152+static void skip_secondary_keys(char *create_str, my_bool has_pk)
153+{
154+ char *ptr, *strend;
155+ char *last_comma= NULL;
156+ my_bool pk_processed= FALSE;
157+ char *autoinc_column= NULL;
158+ my_bool has_autoinc= FALSE;
159+ key_type_t type;
160+
161+ strend= create_str + strlen(create_str);
162+
163+ ptr= create_str;
164+ while (*ptr)
165+ {
166+ char *tmp, *orig_ptr, c;
167+
168+ orig_ptr= ptr;
169+ /* Skip leading whitespace */
170+ while (*ptr && my_isspace(charset_info, *ptr))
171+ ptr++;
172+
173+ /* Read the next line */
174+ for (tmp= ptr; *tmp != '\n' && *tmp != '\0'; tmp++);
175+
176+ c= *tmp;
177+ *tmp= '\0'; /* so strstr() only processes the current line */
178+
179+ if (!strncmp(ptr, "UNIQUE KEY ", sizeof("UNIQUE KEY ") - 1))
180+ type= KEY_TYPE_UNIQUE;
181+ else if (!strncmp(ptr, "KEY ", sizeof("KEY ") - 1))
182+ type= KEY_TYPE_NON_UNIQUE;
183+ else if (!strncmp(ptr, "PRIMARY KEY ", sizeof("PRIMARY KEY ") - 1))
184+ type= KEY_TYPE_PRIMARY;
185+ else
186+ type= KEY_TYPE_NONE;
187+
188+ has_autoinc= (type != KEY_TYPE_NONE) ?
189+ contains_autoinc_column(autoinc_column, ptr, type) : FALSE;
190+
191+ /* Is it a secondary index definition? */
192+ if (c == '\n' &&
193+ ((type == KEY_TYPE_UNIQUE && (pk_processed || !has_pk)) ||
194+ type == KEY_TYPE_NON_UNIQUE) && !has_autoinc)
195+ {
196+ char *data, *end= tmp - 1;
197+
198+ /* Remove the trailing comma */
199+ if (*end == ',')
200+ end--;
201+ data= my_strndup(ptr, end - ptr + 1, MYF(MY_FAE));
202+ skipped_keys_list= list_cons(data, skipped_keys_list);
203+
204+ memmove(orig_ptr, tmp + 1, strend - tmp);
205+ ptr= orig_ptr;
206+ strend-= tmp + 1 - ptr;
207+
208+ /* Remove the comma on the previos line */
209+ if (last_comma != NULL)
210+ {
211+ *last_comma= ' ';
212+ }
213+ }
214+ else
215+ {
216+ char *end;
217+
218+ if (last_comma != NULL && *ptr != ')')
219+ {
220+ /*
221+ It's not the last line of CREATE TABLE, so we have skipped a key
222+ definition. We have to restore the last removed comma.
223+ */
224+ *last_comma= ',';
225+ }
226+
227+ /*
228+ If we are skipping a key which indexes an AUTO_INCREMENT column, it is
229+ safe to optimize all subsequent keys, i.e. we should not be checking for
230+ that column anymore.
231+ */
232+ if (type != KEY_TYPE_NONE && has_autoinc)
233+ {
234+ DBUG_ASSERT(autoinc_column != NULL);
235+
236+ my_free(autoinc_column);
237+ autoinc_column= NULL;
238+ }
239+
240+ if ((has_pk && type == KEY_TYPE_UNIQUE && !pk_processed) ||
241+ type == KEY_TYPE_PRIMARY)
242+ pk_processed= TRUE;
243+
244+ if (strstr(ptr, "AUTO_INCREMENT") && *ptr == '`')
245+ {
246+ /*
247+ The first secondary key defined on this column later cannot be
248+ skipped, as CREATE TABLE would fail on import. Unless there is a
249+ PRIMARY KEY and it indexes that column.
250+ */
251+ for (end= ptr + 1;
252+ /* Skip double backticks as they are a part of identifier */
253+ *end != '\0' && (*end != '`' || end[1] == '`');
254+ end++)
255+ /* empty */;
256+
257+ if (*end == '`' && end > ptr + 1)
258+ {
259+ DBUG_ASSERT(autoinc_column == NULL);
260+
261+ autoinc_column= my_strndup(ptr + 1, end - ptr - 1, MYF(MY_FAE));
262+ }
263+ }
264+
265+ *tmp= c;
266+
267+ if (tmp[-1] == ',')
268+ last_comma= tmp - 1;
269+ ptr= (*tmp == '\0') ? tmp : tmp + 1;
270+ }
271+ }
272+
273+ my_free(autoinc_column);
274+}
275+
276+/*
277+ Check if the table has a primary key defined either explicitly or
278+ implicitly (i.e. a unique key on non-nullable columns).
279+
280+ SYNOPSIS
281+ my_bool has_primary_key(const char *table_name)
282+
283+ table_name quoted table name
284+
285+ RETURNS TRUE if the table has a primary key
286+
287+ DESCRIPTION
288+*/
289+
290+static my_bool has_primary_key(const char *table_name)
291+{
292+ MYSQL_RES *res= NULL;
293+ MYSQL_ROW row;
294+ char query_buff[QUERY_LENGTH];
295+ my_bool has_pk= TRUE;
296+
297+ my_snprintf(query_buff, sizeof(query_buff),
298+ "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE "
299+ "TABLE_SCHEMA=DATABASE() AND TABLE_NAME='%s' AND "
300+ "COLUMN_KEY='PRI'", table_name);
301+ if (mysql_query(mysql, query_buff) || !(res= mysql_store_result(mysql)) ||
302+ !(row= mysql_fetch_row(res)))
303+ {
304+ fprintf(stderr, "Warning: Couldn't determine if table %s has a "
305+ "primary key (%s). "
306+ "--innodb-optimize-keys may work inefficiently.\n",
307+ table_name, mysql_error(mysql));
308+ goto cleanup;
309+ }
310+
311+ has_pk= atoi(row[0]) > 0;
312+
313+cleanup:
314+ if (res)
315+ mysql_free_result(res);
316+
317+ return has_pk;
318+}
319+
320+
321+/*
322 get_table_structure -- retrievs database structure, prints out corresponding
323 CREATE statement and fills out insert_pat if the table is the type we will
324 be dumping.
325@@ -2484,6 +2751,7 @@
326 my_bool is_log_table;
327 MYSQL_RES *result;
328 MYSQL_ROW row;
329+ my_bool has_pk= FALSE;
330 DBUG_ENTER("get_table_structure");
331 DBUG_PRINT("enter", ("db: %s table: %s", db, table));
332
333@@ -2525,6 +2793,9 @@
334 result_table= quote_name(table, table_buff, 1);
335 opt_quoted_table= quote_name(table, table_buff2, 0);
336
337+ if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
338+ has_pk= has_primary_key(table);
339+
340 if (opt_order_by_primary)
341 order_by= primary_key_fields(result_table);
342
343@@ -2712,6 +2983,9 @@
344
345 row= mysql_fetch_row(result);
346
347+ if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
348+ skip_secondary_keys(row[1], has_pk);
349+
350 is_log_table= general_log_or_slow_log_tables(db, table);
351 if (is_log_table)
352 row[1]+= 13; /* strlen("CREATE TABLE ")= 13 */
353@@ -3363,6 +3637,36 @@
354 }
355
356
357+
358+/*
359+ Perform delayed secondary index creation for --innodb-optimize-keys.
360+*/
361+
362+static void restore_secondary_keys(char *table)
363+{
364+ if (skipped_keys_list)
365+ {
366+ uint keys;
367+ skipped_keys_list= list_reverse(skipped_keys_list);
368+ fprintf(md_result_file, "ALTER TABLE %s ", table);
369+ for (keys= list_length(skipped_keys_list); keys > 0; keys--)
370+ {
371+ LIST *node= skipped_keys_list;
372+ char *def= node->data;
373+
374+ fprintf(md_result_file, "ADD %s%s", def, (keys > 1) ? ", " : ";\n");
375+
376+ skipped_keys_list= list_delete(skipped_keys_list, node);
377+ my_free(def);
378+ my_free(node);
379+ }
380+
381+ DBUG_ASSERT(skipped_keys_list == NULL);
382+ }
383+}
384+
385+
386+
387 /*
388
389 SYNOPSIS
390@@ -3406,11 +3710,15 @@
391 if (strcmp(table_type, "VIEW") == 0)
392 DBUG_VOID_RETURN;
393
394+ result_table= quote_name(table,table_buff, 1);
395+ opt_quoted_table= quote_name(table, table_buff2, 0);
396+
397 /* Check --no-data flag */
398 if (opt_no_data)
399 {
400 verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n",
401 table);
402+ restore_secondary_keys(opt_quoted_table);
403 DBUG_VOID_RETURN;
404 }
405
406@@ -3447,9 +3755,6 @@
407 DBUG_VOID_RETURN;
408 }
409
410- result_table= quote_name(table,table_buff, 1);
411- opt_quoted_table= quote_name(table, table_buff2, 0);
412-
413 verbose_msg("-- Sending SELECT query...\n");
414
415 init_dynamic_string_checked(&query_string, "", 1024, 1024);
416@@ -3838,6 +4143,8 @@
417 goto err;
418 }
419
420+ restore_secondary_keys(opt_quoted_table);
421+
422 /* Moved enable keys to before unlock per bug 15977 */
423 if (opt_disable_keys)
424 {
425
426=== modified file 'Percona-Server/mysql-test/r/mysqld--help-notwin.result'
427--- Percona-Server/mysql-test/r/mysqld--help-notwin.result 2012-12-04 08:24:59 +0000
428+++ Percona-Server/mysql-test/r/mysqld--help-notwin.result 2013-01-25 11:48:25 +0000
429@@ -191,6 +191,10 @@
430 and DISABLED (keep the event scheduler completely
431 deactivated, it cannot be activated run-time)
432 -T, --exit-info[=#] Used for debugging. Use at your own risk.
433+ --expand-fast-index-creation
434+ Enable/disable improvements to the InnoDB fast index
435+ creation functionality. Has no effect when fast index
436+ creation is disabled with the fast-index-creation option
437 --expire-logs-days=#
438 If non-zero, binary logs will be purged after
439 expire_logs_days days; possible purges happen at startup
440@@ -1023,6 +1027,7 @@
441 end-markers-in-json FALSE
442 eq-range-index-dive-limit 10
443 event-scheduler OFF
444+expand-fast-index-creation FALSE
445 expire-logs-days 0
446 explicit-defaults-for-timestamp FALSE
447 external-locking FALSE
448
449=== modified file 'Percona-Server/mysql-test/r/mysqld--help-win.result'
450--- Percona-Server/mysql-test/r/mysqld--help-win.result 2012-12-04 08:24:59 +0000
451+++ Percona-Server/mysql-test/r/mysqld--help-win.result 2013-01-25 11:48:25 +0000
452@@ -191,6 +191,10 @@
453 and DISABLED (keep the event scheduler completely
454 deactivated, it cannot be activated run-time)
455 -T, --exit-info[=#] Used for debugging. Use at your own risk.
456+ --expand-fast-index-creation
457+ Enable/disable improvements to InnoDB fast index creation
458+ functionality. Has no effect when fast index creation is
459+ disabled with the fast-index-creation option
460 --expire-logs-days=#
461 If non-zero, binary logs will be purged after
462 expire_logs_days days; possible purges happen at startup
463@@ -1020,6 +1024,7 @@
464 end-markers-in-json FALSE
465 eq-range-index-dive-limit 10
466 event-scheduler OFF
467+expand-fast-index-creation FALSE
468 expire-logs-days 0
469 explicit-defaults-for-timestamp FALSE
470 external-locking FALSE
471
472=== added file 'Percona-Server/mysql-test/r/percona_expand_fast_index_creation.result'
473--- Percona-Server/mysql-test/r/percona_expand_fast_index_creation.result 1970-01-01 00:00:00 +0000
474+++ Percona-Server/mysql-test/r/percona_expand_fast_index_creation.result 2013-01-25 11:48:25 +0000
475@@ -0,0 +1,78 @@
476+SET expand_fast_index_creation=ON;
477+CREATE TABLE idx (a INT PRIMARY KEY);
478+CREATE TABLE t (a INT PRIMARY KEY AUTO_INCREMENT, b FLOAT, c VARCHAR(15), d VARCHAR(17), z VARCHAR(1)) ENGINE=InnoDB;
479+INSERT INTO t (b) VALUES (RAND());
480+INSERT INTO t (b) SELECT RAND() FROM t;
481+INSERT INTO t (b) SELECT RAND() FROM t;
482+INSERT INTO t (b) SELECT RAND() FROM t;
483+INSERT INTO t (b) SELECT RAND() FROM t;
484+INSERT INTO t (b) SELECT RAND() FROM t;
485+INSERT INTO t (b) SELECT RAND() FROM t;
486+INSERT INTO t (b) SELECT RAND() FROM t;
487+ALTER TABLE t ADD KEY k1(b), ADD KEY k2(a,b), ADD KEY k3(a,b,d), ADD UNIQUE KEY k4(a,c,d);
488+INSERT INTO idx (a) SELECT i.INDEX_ID FROM
489+INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
490+INFORMATION_SCHEMA.INNODB_SYS_TABLES t
491+WHERE
492+t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID;
493+SELECT i.NAME, i.TYPE, i.N_FIELDS, f.NAME, f.POS FROM
494+INFORMATION_SCHEMA.INNODB_SYS_FIELDS f,
495+INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
496+INFORMATION_SCHEMA.INNODB_SYS_TABLES t
497+WHERE
498+t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID AND
499+f.INDEX_ID = i.INDEX_ID
500+ORDER BY
501+i.NAME, f.NAME;
502+NAME TYPE N_FIELDS NAME POS
503+k1 0 1 b 0
504+k2 0 2 a 0
505+k2 0 2 b 1
506+k3 0 3 a 0
507+k3 0 3 b 1
508+k3 0 3 d 2
509+k4 2 3 a 0
510+k4 2 3 c 1
511+k4 2 3 d 2
512+PRIMARY 3 1 a 0
513+TRUNCATE TABLE performance_schema.events_stages_history_long;
514+ALTER TABLE t MODIFY COLUMN z VARCHAR(2);
515+SELECT COUNT(*)
516+FROM performance_schema.events_stages_history_long e,
517+performance_schema.threads t
518+WHERE
519+e.EVENT_NAME = 'stage/sql/restoring secondary keys' AND
520+e.THREAD_ID = t.THREAD_ID AND
521+t.PROCESSLIST_ID = CONNECTION_ID();
522+COUNT(*)
523+1
524+INSERT INTO idx (a) SELECT i.INDEX_ID FROM
525+INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
526+INFORMATION_SCHEMA.INNODB_SYS_TABLES t
527+WHERE
528+t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID;
529+SELECT i.NAME, i.TYPE, i.N_FIELDS, f.NAME, f.POS FROM
530+INFORMATION_SCHEMA.INNODB_SYS_FIELDS f,
531+INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
532+INFORMATION_SCHEMA.INNODB_SYS_TABLES t
533+WHERE
534+t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID AND
535+f.INDEX_ID = i.INDEX_ID
536+ORDER BY
537+i.NAME, f.NAME;
538+NAME TYPE N_FIELDS NAME POS
539+k1 0 1 b 0
540+k2 0 2 a 0
541+k2 0 2 b 1
542+k3 0 3 a 0
543+k3 0 3 b 1
544+k3 0 3 d 2
545+k4 2 3 a 0
546+k4 2 3 c 1
547+k4 2 3 d 2
548+PRIMARY 3 1 a 0
549+SELECT COUNT(DISTINCT a) FROM idx;
550+COUNT(DISTINCT a)
551+10
552+DROP TABLE idx;
553+DROP TABLE t;
554
555=== added file 'Percona-Server/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result'
556--- Percona-Server/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result 1970-01-01 00:00:00 +0000
557+++ Percona-Server/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result 2013-01-25 11:48:25 +0000
558@@ -0,0 +1,443 @@
559+#
560+# Test the --innodb-optimize-keys option.
561+#
562+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, KEY(b)) ENGINE=MyISAM;
563+######################################
564+
565+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
566+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
567+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
568+/*!40101 SET NAMES utf8 */;
569+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
570+/*!40103 SET TIME_ZONE='+00:00' */;
571+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
572+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
573+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
574+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
575+DROP TABLE IF EXISTS `t1`;
576+/*!40101 SET @saved_cs_client = @@character_set_client */;
577+/*!40101 SET character_set_client = utf8 */;
578+CREATE TABLE `t1` (
579+ `a` int(11) NOT NULL,
580+ `b` int(11) DEFAULT NULL,
581+ PRIMARY KEY (`a`),
582+ KEY `b` (`b`)
583+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
584+/*!40101 SET character_set_client = @saved_cs_client */;
585+
586+LOCK TABLES `t1` WRITE;
587+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
588+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
589+UNLOCK TABLES;
590+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
591+
592+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
593+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
594+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
595+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
596+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
597+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
598+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
599+
600+######################################
601+DROP TABLE t1;
602+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
603+INSERT INTO t2 VALUES (0), (1), (2);
604+CREATE TABLE t1 (
605+id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
606+a INT, b VARCHAR(255), c DECIMAL(10,3),
607+KEY (b),
608+UNIQUE KEY uniq(c,a),
609+FOREIGN KEY (a) REFERENCES t2(a) ON DELETE CASCADE
610+) ENGINE=InnoDB;
611+INSERT INTO t1(a,b,c) VALUES (0, "0", 0.0), (1, "1", 1.1), (2, "2", 2.2);
612+######################################
613+
614+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
615+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
616+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
617+/*!40101 SET NAMES utf8 */;
618+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
619+/*!40103 SET TIME_ZONE='+00:00' */;
620+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
621+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
622+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
623+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
624+DROP TABLE IF EXISTS `t1`;
625+/*!40101 SET @saved_cs_client = @@character_set_client */;
626+/*!40101 SET character_set_client = utf8 */;
627+CREATE TABLE `t1` (
628+ `id` int(11) NOT NULL AUTO_INCREMENT,
629+ `a` int(11) DEFAULT NULL,
630+ `b` varchar(255) DEFAULT NULL,
631+ `c` decimal(10,3) DEFAULT NULL,
632+ PRIMARY KEY (`id`),
633+ CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`) ON DELETE CASCADE
634+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
635+/*!40101 SET character_set_client = @saved_cs_client */;
636+
637+LOCK TABLES `t1` WRITE;
638+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
639+INSERT INTO `t1` VALUES (1,0,'0',0.000),(2,1,'1',1.100),(3,2,'2',2.200);
640+ALTER TABLE `t1` ADD UNIQUE KEY `uniq` (`c`,`a`), ADD KEY `b` (`b`), ADD KEY `a` (`a`);
641+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
642+UNLOCK TABLES;
643+DROP TABLE IF EXISTS `t2`;
644+/*!40101 SET @saved_cs_client = @@character_set_client */;
645+/*!40101 SET character_set_client = utf8 */;
646+CREATE TABLE `t2` (
647+ `a` int(11) NOT NULL,
648+ PRIMARY KEY (`a`)
649+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
650+/*!40101 SET character_set_client = @saved_cs_client */;
651+
652+LOCK TABLES `t2` WRITE;
653+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
654+INSERT INTO `t2` VALUES (0),(1),(2);
655+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
656+UNLOCK TABLES;
657+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
658+
659+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
660+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
661+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
662+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
663+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
664+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
665+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
666+
667+######################################
668+DROP TABLE t1, t2;
669+CREATE TABLE t1 (
670+id INT NOT NULL AUTO_INCREMENT,
671+KEY (id)
672+) ENGINE=InnoDB;
673+CREATE TABLE t2 (
674+id INT NOT NULL AUTO_INCREMENT,
675+UNIQUE KEY (id)
676+) ENGINE=InnoDB;
677+INSERT INTO t1 VALUES (), (), ();
678+INSERT INTO t2 VALUES (), (), ();
679+######################################
680+
681+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
682+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
683+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
684+/*!40101 SET NAMES utf8 */;
685+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
686+/*!40103 SET TIME_ZONE='+00:00' */;
687+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
688+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
689+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
690+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
691+DROP TABLE IF EXISTS `t1`;
692+/*!40101 SET @saved_cs_client = @@character_set_client */;
693+/*!40101 SET character_set_client = utf8 */;
694+CREATE TABLE `t1` (
695+ `id` int(11) NOT NULL AUTO_INCREMENT,
696+ KEY `id` (`id`)
697+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
698+/*!40101 SET character_set_client = @saved_cs_client */;
699+
700+LOCK TABLES `t1` WRITE;
701+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
702+INSERT INTO `t1` VALUES (1),(2),(3);
703+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
704+UNLOCK TABLES;
705+DROP TABLE IF EXISTS `t2`;
706+/*!40101 SET @saved_cs_client = @@character_set_client */;
707+/*!40101 SET character_set_client = utf8 */;
708+CREATE TABLE `t2` (
709+ `id` int(11) NOT NULL AUTO_INCREMENT,
710+ UNIQUE KEY `id` (`id`)
711+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
712+/*!40101 SET character_set_client = @saved_cs_client */;
713+
714+LOCK TABLES `t2` WRITE;
715+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
716+INSERT INTO `t2` VALUES (1),(2),(3);
717+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
718+UNLOCK TABLES;
719+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
720+
721+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
722+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
723+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
724+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
725+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
726+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
727+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
728+
729+######################################
730+DROP TABLE t1, t2;
731+CREATE TABLE t1 (
732+a INT NOT NULL,
733+UNIQUE KEY (a)) ENGINE=InnoDB;
734+CREATE TABLE t2 (
735+a INT NOT NULL,
736+b INT NOT NULL,
737+UNIQUE KEY (a,b)) ENGINE=InnoDB;
738+CREATE TABLE t3 (
739+a INT,
740+b INT,
741+UNIQUE KEY (a,b)) ENGINE=InnoDB;
742+CREATE TABLE t4 (
743+a INT NOT NULL,
744+b INT NOT NULL,
745+PRIMARY KEY (a,b),
746+UNIQUE KEY(b)) ENGINE=InnoDB;
747+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
748+TABLE_SCHEMA=DATABASE() AND
749+TABLE_NAME='t1' AND
750+COLUMN_KEY='PRI';
751+COUNT(*)
752+1
753+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
754+TABLE_SCHEMA=DATABASE() AND
755+TABLE_NAME='t2' AND
756+COLUMN_KEY='PRI';
757+COUNT(*)
758+2
759+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
760+TABLE_SCHEMA=DATABASE() AND
761+TABLE_NAME='t3' AND
762+COLUMN_KEY='PRI';
763+COUNT(*)
764+0
765+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
766+TABLE_SCHEMA=DATABASE() AND
767+TABLE_NAME='t4' AND
768+COLUMN_KEY='PRI';
769+COUNT(*)
770+2
771+INSERT INTO t1 VALUES (1), (2), (3);
772+INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
773+INSERT INTO t3 SELECT * FROM t2;
774+INSERT INTO t4 SELECT * FROM t2;
775+######################################
776+
777+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
778+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
779+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
780+/*!40101 SET NAMES utf8 */;
781+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
782+/*!40103 SET TIME_ZONE='+00:00' */;
783+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
784+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
785+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
786+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
787+DROP TABLE IF EXISTS `t1`;
788+/*!40101 SET @saved_cs_client = @@character_set_client */;
789+/*!40101 SET character_set_client = utf8 */;
790+CREATE TABLE `t1` (
791+ `a` int(11) NOT NULL,
792+ UNIQUE KEY `a` (`a`)
793+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
794+/*!40101 SET character_set_client = @saved_cs_client */;
795+
796+LOCK TABLES `t1` WRITE;
797+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
798+INSERT INTO `t1` VALUES (1),(2),(3);
799+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
800+UNLOCK TABLES;
801+DROP TABLE IF EXISTS `t2`;
802+/*!40101 SET @saved_cs_client = @@character_set_client */;
803+/*!40101 SET character_set_client = utf8 */;
804+CREATE TABLE `t2` (
805+ `a` int(11) NOT NULL,
806+ `b` int(11) NOT NULL,
807+ UNIQUE KEY `a` (`a`,`b`)
808+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
809+/*!40101 SET character_set_client = @saved_cs_client */;
810+
811+LOCK TABLES `t2` WRITE;
812+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
813+INSERT INTO `t2` VALUES (1,1),(2,2),(3,3);
814+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
815+UNLOCK TABLES;
816+DROP TABLE IF EXISTS `t3`;
817+/*!40101 SET @saved_cs_client = @@character_set_client */;
818+/*!40101 SET character_set_client = utf8 */;
819+CREATE TABLE `t3` (
820+ `a` int(11) DEFAULT NULL,
821+ `b` int(11) DEFAULT NULL
822+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
823+/*!40101 SET character_set_client = @saved_cs_client */;
824+
825+LOCK TABLES `t3` WRITE;
826+/*!40000 ALTER TABLE `t3` DISABLE KEYS */;
827+INSERT INTO `t3` VALUES (1,1),(2,2),(3,3);
828+ALTER TABLE `t3` ADD UNIQUE KEY `a` (`a`,`b`);
829+/*!40000 ALTER TABLE `t3` ENABLE KEYS */;
830+UNLOCK TABLES;
831+DROP TABLE IF EXISTS `t4`;
832+/*!40101 SET @saved_cs_client = @@character_set_client */;
833+/*!40101 SET character_set_client = utf8 */;
834+CREATE TABLE `t4` (
835+ `a` int(11) NOT NULL,
836+ `b` int(11) NOT NULL,
837+ PRIMARY KEY (`a`,`b`)
838+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
839+/*!40101 SET character_set_client = @saved_cs_client */;
840+
841+LOCK TABLES `t4` WRITE;
842+/*!40000 ALTER TABLE `t4` DISABLE KEYS */;
843+INSERT INTO `t4` VALUES (1,1),(2,2),(3,3);
844+ALTER TABLE `t4` ADD UNIQUE KEY `b` (`b`);
845+/*!40000 ALTER TABLE `t4` ENABLE KEYS */;
846+UNLOCK TABLES;
847+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
848+
849+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
850+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
851+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
852+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
853+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
854+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
855+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
856+
857+######################################
858+DROP TABLE t1, t2, t3, t4;
859+CREATE TABLE t1 (
860+id INT NOT NULL PRIMARY KEY
861+) ENGINE=InnoDB;
862+CREATE TABLE t2 (
863+id INT NOT NULL AUTO_INCREMENT,
864+a INT NOT NULL,
865+PRIMARY KEY (id),
866+KEY (a),
867+FOREIGN KEY (a) REFERENCES t2 (id)
868+) ENGINE=InnoDB;
869+INSERT INTO t1 VALUES (1), (2), (3);
870+INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
871+######################################
872+
873+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
874+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
875+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
876+/*!40101 SET NAMES utf8 */;
877+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
878+/*!40103 SET TIME_ZONE='+00:00' */;
879+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
880+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
881+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
882+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
883+DROP TABLE IF EXISTS `t1`;
884+/*!40101 SET @saved_cs_client = @@character_set_client */;
885+/*!40101 SET character_set_client = utf8 */;
886+CREATE TABLE `t1` (
887+ `id` int(11) NOT NULL,
888+ PRIMARY KEY (`id`)
889+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
890+/*!40101 SET character_set_client = @saved_cs_client */;
891+
892+LOCK TABLES `t1` WRITE;
893+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
894+INSERT INTO `t1` VALUES (1),(2),(3);
895+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
896+UNLOCK TABLES;
897+DROP TABLE IF EXISTS `t2`;
898+/*!40101 SET @saved_cs_client = @@character_set_client */;
899+/*!40101 SET character_set_client = utf8 */;
900+CREATE TABLE `t2` (
901+ `id` int(11) NOT NULL AUTO_INCREMENT,
902+ `a` int(11) NOT NULL,
903+ PRIMARY KEY (`id`),
904+ CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`id`)
905+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
906+/*!40101 SET character_set_client = @saved_cs_client */;
907+
908+LOCK TABLES `t2` WRITE;
909+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
910+INSERT INTO `t2` VALUES (1,1),(2,2),(3,3);
911+ALTER TABLE `t2` ADD KEY `a` (`a`);
912+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
913+UNLOCK TABLES;
914+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
915+
916+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
917+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
918+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
919+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
920+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
921+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
922+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
923+
924+######################################
925+DROP TABLE t1, t2;
926+CREATE TABLE t1 (
927+id INT NOT NULL AUTO_INCREMENT,
928+uid INT NOT NULL,
929+`id``` INT NOT NULL,
930+```id` INT NOT NULL,
931+# The following ones may be skipped and used in ALTER TABLE later
932+KEY k1 (```id`, id),
933+KEY k2 (```id`, `id```),
934+# The following one should be kept in CREATE TABLE
935+KEY k3 (id, uid),
936+# The following one may be skipped again
937+KEY k4 (id, `id```)
938+) ENGINE=InnoDB;
939+CREATE TABLE t2 (
940+id INT NOT NULL AUTO_INCREMENT,
941+PRIMARY KEY (id),
942+KEY k1 (id),
943+KEY k2 (id)
944+) ENGINE=InnoDB;
945+Warnings:
946+Note 1831 Duplicate index 'k2' defined on the table 'test.t2'. This is deprecated and will be disallowed in a future release.
947+######################################
948+
949+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
950+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
951+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
952+/*!40101 SET NAMES utf8 */;
953+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
954+/*!40103 SET TIME_ZONE='+00:00' */;
955+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
956+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
957+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
958+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
959+DROP TABLE IF EXISTS `t1`;
960+/*!40101 SET @saved_cs_client = @@character_set_client */;
961+/*!40101 SET character_set_client = utf8 */;
962+CREATE TABLE `t1` (
963+ `id` int(11) NOT NULL AUTO_INCREMENT,
964+ `uid` int(11) NOT NULL,
965+ `id``` int(11) NOT NULL,
966+ ```id` int(11) NOT NULL,
967+ KEY `k3` (`id`,`uid`)
968+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
969+/*!40101 SET character_set_client = @saved_cs_client */;
970+
971+LOCK TABLES `t1` WRITE;
972+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
973+ALTER TABLE `t1` ADD KEY `k1` (```id`,`id`), ADD KEY `k2` (```id`,`id```), ADD KEY `k4` (`id`,`id```);
974+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
975+UNLOCK TABLES;
976+DROP TABLE IF EXISTS `t2`;
977+/*!40101 SET @saved_cs_client = @@character_set_client */;
978+/*!40101 SET character_set_client = utf8 */;
979+CREATE TABLE `t2` (
980+ `id` int(11) NOT NULL AUTO_INCREMENT,
981+ PRIMARY KEY (`id`)
982+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
983+/*!40101 SET character_set_client = @saved_cs_client */;
984+
985+LOCK TABLES `t2` WRITE;
986+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
987+ALTER TABLE `t2` ADD KEY `k1` (`id`), ADD KEY `k2` (`id`);
988+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
989+UNLOCK TABLES;
990+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
991+
992+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
993+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
994+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
995+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
996+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
997+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
998+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
999+
1000+######################################
1001+DROP TABLE t1, t2;
1002
1003=== added file 'Percona-Server/mysql-test/suite/innodb/r/percona_bug_999147.result'
1004--- Percona-Server/mysql-test/suite/innodb/r/percona_bug_999147.result 1970-01-01 00:00:00 +0000
1005+++ Percona-Server/mysql-test/suite/innodb/r/percona_bug_999147.result 2013-01-25 11:48:25 +0000
1006@@ -0,0 +1,17 @@
1007+DROP TABLE IF EXISTS t1;
1008+SET SESSION expand_fast_index_creation=ON;
1009+CREATE TEMPORARY TABLE t1 (a INT, b INT, INDEX(a));
1010+SET debug="+d,crash_innodb_add_index_after";
1011+ALTER TABLE t1 ADD INDEX (b);
1012+ERROR HY000: Lost connection to MySQL server during query
1013+SELECT NAME, FLAG FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES;
1014+NAME FLAG
1015+SYS_DATAFILES 0
1016+SYS_FOREIGN 0
1017+SYS_FOREIGN_COLS 0
1018+SYS_TABLESPACES 0
1019+mysql/innodb_index_stats 1
1020+mysql/innodb_table_stats 1
1021+mysql/slave_master_info 1
1022+mysql/slave_relay_log_info 1
1023+mysql/slave_worker_info 1
1024
1025=== added file 'Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147-master.opt'
1026--- Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147-master.opt 1970-01-01 00:00:00 +0000
1027+++ Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147-master.opt 2013-01-25 11:48:25 +0000
1028@@ -0,0 +1,1 @@
1029+--skip-stack-trace --skip-core-file --innodb-file-per-table=1
1030
1031=== added file 'Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147.test'
1032--- Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147.test 1970-01-01 00:00:00 +0000
1033+++ Percona-Server/mysql-test/suite/innodb/t/percona_bug_999147.test 2013-01-25 11:48:25 +0000
1034@@ -0,0 +1,29 @@
1035+# Test for Percona Server bug 999147 (A crash that leaves behind an
1036+# InnoDB temporary table with indexes results in an unbootable server)
1037+# https://bugs.launchpad.net/percona-server/+bug/999147
1038+
1039+-- source include/not_embedded.inc
1040+-- source include/not_valgrind.inc
1041+-- source include/not_crashrep.inc
1042+-- source include/have_debug.inc
1043+-- source include/have_innodb.inc
1044+
1045+--disable_warnings
1046+DROP TABLE IF EXISTS t1;
1047+--enable_warnings
1048+
1049+SET SESSION expand_fast_index_creation=ON;
1050+
1051+CREATE TEMPORARY TABLE t1 (a INT, b INT, INDEX(a));
1052+
1053+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
1054+
1055+SET debug="+d,crash_innodb_add_index_after";
1056+--error 2013
1057+ALTER TABLE t1 ADD INDEX (b);
1058+
1059+--enable_reconnect
1060+
1061+--source include/wait_until_connected_again.inc
1062+
1063+SELECT NAME, FLAG FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES;
1064
1065=== added file 'Percona-Server/mysql-test/suite/sys_vars/r/expand_fast_index_creation_basic.result'
1066--- Percona-Server/mysql-test/suite/sys_vars/r/expand_fast_index_creation_basic.result 1970-01-01 00:00:00 +0000
1067+++ Percona-Server/mysql-test/suite/sys_vars/r/expand_fast_index_creation_basic.result 2013-01-25 11:48:25 +0000
1068@@ -0,0 +1,6 @@
1069+SELECT @@global.expand_fast_index_creation;
1070+@@global.expand_fast_index_creation
1071+0
1072+SELECT @@local.expand_fast_index_creation;
1073+@@local.expand_fast_index_creation
1074+0
1075
1076=== added file 'Percona-Server/mysql-test/suite/sys_vars/t/expand_fast_index_creation_basic.test'
1077--- Percona-Server/mysql-test/suite/sys_vars/t/expand_fast_index_creation_basic.test 1970-01-01 00:00:00 +0000
1078+++ Percona-Server/mysql-test/suite/sys_vars/t/expand_fast_index_creation_basic.test 2013-01-25 11:48:25 +0000
1079@@ -0,0 +1,2 @@
1080+SELECT @@global.expand_fast_index_creation;
1081+SELECT @@local.expand_fast_index_creation;
1082
1083=== added file 'Percona-Server/mysql-test/t/percona_expand_fast_index_creation.test'
1084--- Percona-Server/mysql-test/t/percona_expand_fast_index_creation.test 1970-01-01 00:00:00 +0000
1085+++ Percona-Server/mysql-test/t/percona_expand_fast_index_creation.test 2013-01-25 11:48:25 +0000
1086@@ -0,0 +1,77 @@
1087+######################################################################
1088+# Expand Fast Index Creation test
1089+# Here we perform some DDL and ensure that Expand Fast Index Creation
1090+# worked correctly
1091+######################################################################
1092+
1093+--source include/have_perfschema.inc
1094+
1095+SET expand_fast_index_creation=ON;
1096+CREATE TABLE idx (a INT PRIMARY KEY);
1097+CREATE TABLE t (a INT PRIMARY KEY AUTO_INCREMENT, b FLOAT, c VARCHAR(15), d VARCHAR(17), z VARCHAR(1)) ENGINE=InnoDB;
1098+INSERT INTO t (b) VALUES (RAND());
1099+INSERT INTO t (b) SELECT RAND() FROM t;
1100+INSERT INTO t (b) SELECT RAND() FROM t;
1101+INSERT INTO t (b) SELECT RAND() FROM t;
1102+INSERT INTO t (b) SELECT RAND() FROM t;
1103+INSERT INTO t (b) SELECT RAND() FROM t;
1104+INSERT INTO t (b) SELECT RAND() FROM t;
1105+INSERT INTO t (b) SELECT RAND() FROM t;
1106+ALTER TABLE t ADD KEY k1(b), ADD KEY k2(a,b), ADD KEY k3(a,b,d), ADD UNIQUE KEY k4(a,c,d);
1107+
1108+# store InnoDB ID's of INDEXES for t
1109+INSERT INTO idx (a) SELECT i.INDEX_ID FROM
1110+ INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
1111+ INFORMATION_SCHEMA.INNODB_SYS_TABLES t
1112+WHERE
1113+ t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID;
1114+
1115+# confirm that there are two indexes
1116+SELECT i.NAME, i.TYPE, i.N_FIELDS, f.NAME, f.POS FROM
1117+ INFORMATION_SCHEMA.INNODB_SYS_FIELDS f,
1118+ INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
1119+ INFORMATION_SCHEMA.INNODB_SYS_TABLES t
1120+WHERE
1121+ t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID AND
1122+ f.INDEX_ID = i.INDEX_ID
1123+ORDER BY
1124+ i.NAME, f.NAME;
1125+
1126+# truncate older stages
1127+TRUNCATE TABLE performance_schema.events_stages_history_long;
1128+
1129+# perform alter
1130+ALTER TABLE t MODIFY COLUMN z VARCHAR(2);
1131+
1132+# make sure expand fast index creation worked
1133+SELECT COUNT(*)
1134+ FROM performance_schema.events_stages_history_long e,
1135+ performance_schema.threads t
1136+ WHERE
1137+ e.EVENT_NAME = 'stage/sql/restoring secondary keys' AND
1138+ e.THREAD_ID = t.THREAD_ID AND
1139+ t.PROCESSLIST_ID = CONNECTION_ID();
1140+
1141+# store new index ID's
1142+INSERT INTO idx (a) SELECT i.INDEX_ID FROM
1143+ INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
1144+ INFORMATION_SCHEMA.INNODB_SYS_TABLES t
1145+WHERE
1146+ t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID;
1147+
1148+# confirm that there are two indexes
1149+SELECT i.NAME, i.TYPE, i.N_FIELDS, f.NAME, f.POS FROM
1150+ INFORMATION_SCHEMA.INNODB_SYS_FIELDS f,
1151+ INFORMATION_SCHEMA.INNODB_SYS_INDEXES i,
1152+ INFORMATION_SCHEMA.INNODB_SYS_TABLES t
1153+WHERE
1154+ t.NAME = 'test/t' AND i.TABLE_ID = t.TABLE_ID AND
1155+ f.INDEX_ID = i.INDEX_ID
1156+ORDER BY
1157+ i.NAME, f.NAME;
1158+
1159+# confirm that there are four different ID's
1160+SELECT COUNT(DISTINCT a) FROM idx;
1161+
1162+DROP TABLE idx;
1163+DROP TABLE t;
1164
1165=== added file 'Percona-Server/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test'
1166--- Percona-Server/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test 1970-01-01 00:00:00 +0000
1167+++ Percona-Server/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test 2013-01-25 11:48:25 +0000
1168@@ -0,0 +1,227 @@
1169+# Embedded server doesn't support external clients
1170+--source include/not_embedded.inc
1171+
1172+# Fast index creation is only available in InnoDB plugin
1173+--source include/have_innodb.inc
1174+
1175+# Save the initial number of concurrent sessions
1176+--source include/count_sessions.inc
1177+
1178+--echo #
1179+--echo # Test the --innodb-optimize-keys option.
1180+--echo #
1181+
1182+--let $file=$MYSQLTEST_VARDIR/tmp/t1.sql
1183+
1184+# First test that the option has no effect on non-InnoDB tables
1185+
1186+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, KEY(b)) ENGINE=MyISAM;
1187+
1188+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 >$file
1189+
1190+--echo ######################################
1191+--cat_file $file
1192+--echo ######################################
1193+
1194+--remove_file $file
1195+
1196+DROP TABLE t1;
1197+
1198+# Check that for InnoDB tables secondary keys are created after the data is
1199+# dumped but foreign ones are left in CREATE TABLE
1200+
1201+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
1202+INSERT INTO t2 VALUES (0), (1), (2);
1203+
1204+CREATE TABLE t1 (
1205+ id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
1206+ a INT, b VARCHAR(255), c DECIMAL(10,3),
1207+ KEY (b),
1208+ UNIQUE KEY uniq(c,a),
1209+ FOREIGN KEY (a) REFERENCES t2(a) ON DELETE CASCADE
1210+) ENGINE=InnoDB;
1211+
1212+INSERT INTO t1(a,b,c) VALUES (0, "0", 0.0), (1, "1", 1.1), (2, "2", 2.2);
1213+
1214+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
1215+
1216+--echo ######################################
1217+--cat_file $file
1218+--echo ######################################
1219+
1220+# Check that the resulting dump can be imported back
1221+
1222+--exec $MYSQL test < $file
1223+
1224+--remove_file $file
1225+
1226+DROP TABLE t1, t2;
1227+
1228+########################################################################
1229+# Bug #812179: AUTO_INCREMENT columns must be skipped by the
1230+# --innodb-optimize-keys optimization in mysqldump
1231+########################################################################
1232+
1233+CREATE TABLE t1 (
1234+ id INT NOT NULL AUTO_INCREMENT,
1235+ KEY (id)
1236+) ENGINE=InnoDB;
1237+
1238+CREATE TABLE t2 (
1239+ id INT NOT NULL AUTO_INCREMENT,
1240+ UNIQUE KEY (id)
1241+) ENGINE=InnoDB;
1242+
1243+INSERT INTO t1 VALUES (), (), ();
1244+INSERT INTO t2 VALUES (), (), ();
1245+
1246+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
1247+
1248+--echo ######################################
1249+--cat_file $file
1250+--echo ######################################
1251+
1252+# Check that the resulting dump can be imported back
1253+
1254+--exec $MYSQL test < $file
1255+
1256+--remove_file $file
1257+
1258+DROP TABLE t1, t2;
1259+
1260+########################################################################
1261+# Bug #851674: --innodb-optimize-keys does not work correctly with table
1262+# without PRIMARY KEY
1263+########################################################################
1264+
1265+CREATE TABLE t1 (
1266+ a INT NOT NULL,
1267+ UNIQUE KEY (a)) ENGINE=InnoDB;
1268+
1269+CREATE TABLE t2 (
1270+ a INT NOT NULL,
1271+ b INT NOT NULL,
1272+ UNIQUE KEY (a,b)) ENGINE=InnoDB;
1273+
1274+CREATE TABLE t3 (
1275+ a INT,
1276+ b INT,
1277+ UNIQUE KEY (a,b)) ENGINE=InnoDB;
1278+
1279+CREATE TABLE t4 (
1280+ a INT NOT NULL,
1281+ b INT NOT NULL,
1282+ PRIMARY KEY (a,b),
1283+ UNIQUE KEY(b)) ENGINE=InnoDB;
1284+
1285+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
1286+ TABLE_SCHEMA=DATABASE() AND
1287+ TABLE_NAME='t1' AND
1288+ COLUMN_KEY='PRI';
1289+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
1290+ TABLE_SCHEMA=DATABASE() AND
1291+ TABLE_NAME='t2' AND
1292+ COLUMN_KEY='PRI';
1293+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
1294+ TABLE_SCHEMA=DATABASE() AND
1295+ TABLE_NAME='t3' AND
1296+ COLUMN_KEY='PRI';
1297+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
1298+ TABLE_SCHEMA=DATABASE() AND
1299+ TABLE_NAME='t4' AND
1300+ COLUMN_KEY='PRI';
1301+
1302+INSERT INTO t1 VALUES (1), (2), (3);
1303+INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
1304+INSERT INTO t3 SELECT * FROM t2;
1305+INSERT INTO t4 SELECT * FROM t2;
1306+
1307+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 t3 t4 >$file
1308+
1309+--echo ######################################
1310+--cat_file $file
1311+--echo ######################################
1312+
1313+# Check that the resulting dump can be imported back
1314+
1315+--exec $MYSQL test < $file
1316+
1317+--remove_file $file
1318+
1319+DROP TABLE t1, t2, t3, t4;
1320+
1321+########################################################################
1322+# Bug #859078: --innodb-optimize-keys should ignore foreign keys
1323+########################################################################
1324+
1325+CREATE TABLE t1 (
1326+ id INT NOT NULL PRIMARY KEY
1327+) ENGINE=InnoDB;
1328+
1329+CREATE TABLE t2 (
1330+ id INT NOT NULL AUTO_INCREMENT,
1331+ a INT NOT NULL,
1332+ PRIMARY KEY (id),
1333+ KEY (a),
1334+ FOREIGN KEY (a) REFERENCES t2 (id)
1335+) ENGINE=InnoDB;
1336+
1337+INSERT INTO t1 VALUES (1), (2), (3);
1338+INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
1339+
1340+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
1341+
1342+--echo ######################################
1343+--cat_file $file
1344+--echo ######################################
1345+
1346+# Check that the resulting dump can be imported back
1347+
1348+--exec $MYSQL test < $file
1349+
1350+--remove_file $file
1351+
1352+DROP TABLE t1, t2;
1353+
1354+########################################################################
1355+# Bug #1039536: mysqldump --innodb-optimize-keys can generate invalid table
1356+# definitions
1357+########################################################################
1358+
1359+CREATE TABLE t1 (
1360+ id INT NOT NULL AUTO_INCREMENT,
1361+ uid INT NOT NULL,
1362+ `id``` INT NOT NULL,
1363+ ```id` INT NOT NULL,
1364+ # The following ones may be skipped and used in ALTER TABLE later
1365+ KEY k1 (```id`, id),
1366+ KEY k2 (```id`, `id```),
1367+ # The following one should be kept in CREATE TABLE
1368+ KEY k3 (id, uid),
1369+ # The following one may be skipped again
1370+ KEY k4 (id, `id```)
1371+) ENGINE=InnoDB;
1372+
1373+CREATE TABLE t2 (
1374+ id INT NOT NULL AUTO_INCREMENT,
1375+ PRIMARY KEY (id),
1376+ KEY k1 (id),
1377+ KEY k2 (id)
1378+) ENGINE=InnoDB;
1379+
1380+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
1381+
1382+--echo ######################################
1383+--cat_file $file
1384+--echo ######################################
1385+
1386+# Check that the resulting dump can be imported back
1387+
1388+--exec $MYSQL test < $file
1389+
1390+--remove_file $file
1391+
1392+DROP TABLE t1, t2;
1393+
1394+# Wait till we reached the initial number of concurrent sessions
1395+--source include/wait_until_count_sessions.inc
1396
1397=== modified file 'Percona-Server/sql/handler.cc'
1398--- Percona-Server/sql/handler.cc 2012-12-04 08:24:59 +0000
1399+++ Percona-Server/sql/handler.cc 2013-01-25 11:48:25 +0000
1400@@ -4256,12 +4256,14 @@
1401 The exception is if we're about to roll back changes (commit= false).
1402 In this case, we might be rolling back after a failed lock upgrade,
1403 so we could be holding the same lock level as for inplace_alter_table().
1404+ TABLE::mdl_ticket is 0 for temporary tables.
1405 */
1406- DBUG_ASSERT(ha_thd()->mdl_context.is_lock_owner(MDL_key::TABLE,
1407+ DBUG_ASSERT((table->s->tmp_table != NO_TMP_TABLE && !table->mdl_ticket) ||
1408+ (ha_thd()->mdl_context.is_lock_owner(MDL_key::TABLE,
1409 table->s->db.str,
1410 table->s->table_name.str,
1411 MDL_EXCLUSIVE) ||
1412- !commit);
1413+ !commit));
1414
1415 return commit_inplace_alter_table(altered_table, ha_alter_info, commit);
1416 }
1417
1418=== modified file 'Percona-Server/sql/mysqld.cc'
1419--- Percona-Server/sql/mysqld.cc 2012-12-04 08:24:59 +0000
1420+++ Percona-Server/sql/mysqld.cc 2013-01-25 11:48:25 +0000
1421@@ -9440,6 +9440,7 @@
1422 PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0};
1423 PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0};
1424 PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0};
1425+PSI_stage_info stage_restoring_secondary_keys= { 0, "restoring secondary keys", 0};
1426
1427 #ifdef HAVE_PSI_INTERFACE
1428
1429@@ -9537,7 +9538,8 @@
1430 & stage_waiting_for_the_next_event_in_relay_log,
1431 & stage_waiting_for_the_slave_thread_to_advance_position,
1432 & stage_waiting_to_finalize_termination,
1433- & stage_waiting_to_get_readlock
1434+ & stage_waiting_to_get_readlock,
1435+ & stage_restoring_secondary_keys
1436 };
1437
1438 PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection;
1439
1440=== modified file 'Percona-Server/sql/mysqld.h'
1441--- Percona-Server/sql/mysqld.h 2012-12-04 08:24:59 +0000
1442+++ Percona-Server/sql/mysqld.h 2013-01-25 11:48:25 +0000
1443@@ -492,6 +492,7 @@
1444 extern PSI_stage_info stage_slave_waiting_worker_queue;
1445 extern PSI_stage_info stage_slave_waiting_event_from_coordinator;
1446 extern PSI_stage_info stage_slave_waiting_workers_to_exit;
1447+extern PSI_stage_info stage_restoring_secondary_keys;
1448 #ifdef HAVE_PSI_STATEMENT_INTERFACE
1449 /**
1450 Statement instrumentation keys (sql).
1451
1452=== modified file 'Percona-Server/sql/sql_alter.cc'
1453--- Percona-Server/sql/sql_alter.cc 2012-10-16 06:21:51 +0000
1454+++ Percona-Server/sql/sql_alter.cc 2013-01-25 11:48:25 +0000
1455@@ -25,6 +25,9 @@
1456 alter_list(rhs.alter_list, mem_root),
1457 key_list(rhs.key_list, mem_root),
1458 create_list(rhs.create_list, mem_root),
1459+ delayed_key_list(rhs.delayed_key_list, mem_root),
1460+ delayed_key_info(rhs.delayed_key_info),
1461+ delayed_key_count(rhs.delayed_key_count),
1462 flags(rhs.flags),
1463 keys_onoff(rhs.keys_onoff),
1464 partition_names(rhs.partition_names, mem_root),
1465@@ -45,6 +48,7 @@
1466 list_copy_and_replace_each_value(alter_list, mem_root);
1467 list_copy_and_replace_each_value(key_list, mem_root);
1468 list_copy_and_replace_each_value(create_list, mem_root);
1469+ list_copy_and_replace_each_value(delayed_key_list, mem_root);
1470 /* partition_names are not deeply copied currently */
1471 }
1472
1473
1474=== modified file 'Percona-Server/sql/sql_alter.h'
1475--- Percona-Server/sql/sql_alter.h 2012-10-16 06:21:51 +0000
1476+++ Percona-Server/sql/sql_alter.h 2013-01-25 11:48:25 +0000
1477@@ -171,6 +171,12 @@
1478 List<Key> key_list;
1479 // List of columns, used by both CREATE and ALTER TABLE.
1480 List<Create_field> create_list;
1481+ // List of keys, which creation is delayed to benefit from fast index creation
1482+ List<Key> delayed_key_list;
1483+ // Keys, which creation is delayed to benefit from fast index creation
1484+ KEY *delayed_key_info;
1485+ // Count of keys, which creation is delayed to benefit from fast index creation
1486+ uint delayed_key_count;
1487 // Type of ALTER TABLE operation.
1488 uint flags;
1489 // Enable or disable keys.
1490
1491=== modified file 'Percona-Server/sql/sql_class.h'
1492--- Percona-Server/sql/sql_class.h 2012-12-04 08:24:59 +0000
1493+++ Percona-Server/sql/sql_class.h 2013-01-25 11:48:25 +0000
1494@@ -546,6 +546,7 @@
1495 Gtid_specification gtid_next;
1496 Gtid_set_or_null gtid_next_list;
1497
1498+ my_bool expand_fast_index_creation;
1499 } SV;
1500
1501
1502
1503=== modified file 'Percona-Server/sql/sql_table.cc'
1504--- Percona-Server/sql/sql_table.cc 2012-12-04 08:24:59 +0000
1505+++ Percona-Server/sql/sql_table.cc 2013-01-25 11:48:25 +0000
1506@@ -3634,6 +3634,14 @@
1507 if (!*key_info_buffer || ! key_part_info)
1508 DBUG_RETURN(TRUE); // Out of memory
1509
1510+ List_iterator<Key> delayed_key_iterator(alter_info->delayed_key_list);
1511+ alter_info->delayed_key_count= 0;
1512+ if (alter_info->delayed_key_list.elements > 0)
1513+ {
1514+ alter_info->delayed_key_info= (KEY *) sql_calloc(sizeof(KEY) *
1515+ (*key_count));
1516+ }
1517+
1518 key_iterator.rewind();
1519 key_number=0;
1520 for (; (key=key_iterator++) ; key_number++)
1521@@ -4043,6 +4051,22 @@
1522 // Check if a duplicate index is defined.
1523 check_duplicate_key(thd, key, key_info, &alter_info->key_list);
1524
1525+ if (alter_info->delayed_key_list.elements > 0)
1526+ {
1527+ Key *delayed_key;
1528+
1529+ delayed_key_iterator.rewind();
1530+ while ((delayed_key= delayed_key_iterator++))
1531+ {
1532+ if (delayed_key == key)
1533+ {
1534+ alter_info->delayed_key_info[alter_info->delayed_key_count++]=
1535+ *key_info;
1536+ break;
1537+ }
1538+ }
1539+ }
1540+
1541 key_info++;
1542 }
1543
1544@@ -6522,6 +6546,10 @@
1545 List<Create_field> new_create_list;
1546 /* New key definitions are added here */
1547 List<Key> new_key_list;
1548+ /* List with secondary keys which should be created after copying the data */
1549+ List<Key> delayed_key_list;
1550+ /* Foreign key list returned by handler::get_foreign_key_list() */
1551+ List<FOREIGN_KEY_INFO> f_key_list;
1552 List_iterator<Alter_drop> drop_it(alter_info->drop_list);
1553 List_iterator<Create_field> def_it(alter_info->create_list);
1554 List_iterator<Alter_column> alter_it(alter_info->alter_list);
1555@@ -6534,6 +6562,7 @@
1556 uint used_fields= create_info->used_fields;
1557 KEY *key_info=table->key_info;
1558 bool rc= TRUE;
1559+ bool skip_secondary;
1560
1561 DBUG_ENTER("mysql_prepare_alter_table");
1562
1563@@ -6744,8 +6773,26 @@
1564 /*
1565 Collect all keys which isn't in drop list. Add only those
1566 for which some fields exists.
1567+
1568+ We also store secondary keys in delayed_key_list to make use of
1569+ the InnoDB fast index creation. The following conditions must be
1570+ met:
1571+
1572+ - fast_index_creation is enabled for the current session
1573+ - expand_fast_index_creation is enabled for the current session;
1574+ - we are going to create an InnoDB table (this is checked later when the
1575+ target engine is known);
1576+ - the key most be a non-UNIQUE one;
1577+ - there are no foreign keys. This can be optimized later to exclude only
1578+ those keys which are a part of foreign key constraints. Currently we
1579+ simply disable this optimization for all keys if there are any foreign
1580+ key constraints in the table.
1581 */
1582
1583+ skip_secondary= thd->variables.expand_fast_index_creation &&
1584+ !table->file->get_foreign_key_list(thd, &f_key_list) &&
1585+ f_key_list.elements == 0;
1586+
1587 for (uint i=0 ; i < table->s->keys ; i++,key_info++)
1588 {
1589 char *key_name= key_info->name;
1590@@ -6867,6 +6914,10 @@
1591 test(key_info->flags & HA_GENERATED_KEY),
1592 key_parts);
1593 new_key_list.push_back(key);
1594+
1595+ if (skip_secondary && key_type == Key::MULTIPLE) {
1596+ delayed_key_list.push_back(key);
1597+ }
1598 }
1599 }
1600 {
1601@@ -6874,6 +6925,23 @@
1602 while ((key=key_it++)) // Add new keys
1603 {
1604 new_key_list.push_back(key);
1605+
1606+ if (key->type != Key::FOREIGN_KEY)
1607+ {
1608+ if (skip_secondary && key->type == Key::MULTIPLE) {
1609+ delayed_key_list.push_back(key);
1610+ }
1611+ }
1612+ else if (skip_secondary)
1613+ {
1614+ /*
1615+ We are adding a foreign key so disable the secondary keys
1616+ optimization.
1617+ */
1618+ skip_secondary= FALSE;
1619+ delayed_key_list.empty();
1620+ }
1621+
1622 if (key->name.str &&
1623 !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
1624 {
1625@@ -6941,6 +7009,7 @@
1626 rc= FALSE;
1627 alter_info->create_list.swap(new_create_list);
1628 alter_info->key_list.swap(new_key_list);
1629+ alter_info->delayed_key_list.swap(delayed_key_list);
1630 err:
1631 DBUG_RETURN(rc);
1632 }
1633@@ -7373,6 +7442,131 @@
1634 }
1635
1636
1637+/*
1638+ Temporarily remove secondary keys previously stored in
1639+ alter_info->delayed_key_info.
1640+*/
1641+static int
1642+remove_secondary_keys(THD *thd, HA_CREATE_INFO* create_info, TABLE *table,
1643+ Alter_info *alter_info)
1644+{
1645+ uint i;
1646+ DBUG_ENTER("remove_secondary_keys");
1647+ DBUG_ASSERT(alter_info->delayed_key_count > 0);
1648+
1649+ /*
1650+ We need to mark all fields for read and write as being done in
1651+ mysql_alter_table.
1652+ */
1653+ table->use_all_columns();
1654+
1655+ /*
1656+ Create Alter_info for the table and fill create_list with fields
1657+ definitions. Not that fields not changed, so we set field==ogrig_field.
1658+ */
1659+ Alter_info alter_info_new;
1660+ Field **f_ptr, *field;
1661+
1662+ for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
1663+ {
1664+ Create_field* new_field= new Create_field(field, field);
1665+ alter_info_new.create_list.push_back(new_field);
1666+ }
1667+
1668+ Alter_inplace_info ha_alter_info(create_info, &alter_info_new,
1669+ table->key_info, table->s->keys,
1670+#ifdef WITH_PARTITION_STORAGE_ENGINE
1671+ thd->work_part_info,
1672+#else
1673+ NULL,
1674+#endif
1675+ FALSE);
1676+
1677+ ha_alter_info.handler_flags= Alter_inplace_info::DROP_INDEX;
1678+ ha_alter_info.index_drop_count= alter_info->delayed_key_count;
1679+
1680+ /* Fill index_drop_buffer with keys to drop */
1681+ ha_alter_info.index_drop_buffer= (KEY**) thd->alloc(sizeof(KEY*) *
1682+ alter_info->delayed_key_count);
1683+ for (i= 0; i < alter_info->delayed_key_count; i++)
1684+ ha_alter_info.index_drop_buffer[i] = &(alter_info->delayed_key_info[i]);
1685+
1686+ if (table->file->check_if_supported_inplace_alter(table, &ha_alter_info) ==
1687+ HA_ALTER_INPLACE_NOT_SUPPORTED)
1688+ DBUG_RETURN(-1);
1689+
1690+ if (table->file->ha_prepare_inplace_alter_table(table, &ha_alter_info) ||
1691+ table->file->ha_inplace_alter_table(table, &ha_alter_info) ||
1692+ table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, true))
1693+ {
1694+ table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, false);
1695+ DBUG_RETURN(-1);
1696+ }
1697+
1698+ DBUG_RETURN(0);
1699+}
1700+
1701+/*
1702+ Restore secondary keys previously removed in remove_secondary_keys.
1703+*/
1704+
1705+static int
1706+restore_secondary_keys(THD *thd, HA_CREATE_INFO* create_info, TABLE *table,
1707+ Alter_info *alter_info)
1708+{
1709+ uint i;
1710+ DBUG_ENTER("restore_secondary_keys");
1711+ DBUG_ASSERT(alter_info->delayed_key_count > 0);
1712+
1713+ THD_STAGE_INFO(thd, stage_restoring_secondary_keys);
1714+
1715+ /*
1716+ Create Alter_info for the table and fill create_list with fields
1717+ definitions. Not that fields not changed, so we set field==ogrig_field.
1718+ */
1719+ Alter_info alter_info_new;
1720+ Field **f_ptr, *field;
1721+
1722+ for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
1723+ {
1724+ Create_field* new_field= new Create_field(field, field);
1725+ alter_info_new.create_list.push_back(new_field);
1726+ }
1727+
1728+ Alter_inplace_info ha_alter_info(create_info, &alter_info_new,
1729+ alter_info->delayed_key_info, table->s->keys,
1730+#ifdef WITH_PARTITION_STORAGE_ENGINE
1731+ thd->work_part_info,
1732+#else
1733+ NULL,
1734+#endif
1735+ FALSE);
1736+
1737+ ha_alter_info.handler_flags= Alter_inplace_info::ADD_INDEX;
1738+ ha_alter_info.index_add_count= alter_info->delayed_key_count;
1739+
1740+ ha_alter_info.index_add_buffer= (uint*) thd->alloc(sizeof(uint) *
1741+ alter_info->delayed_key_count);
1742+
1743+ /* Fill index_add_buffer with key indexes from key_info_buffer */
1744+ for (i= 0; i < alter_info->delayed_key_count; i++)
1745+ ha_alter_info.index_add_buffer[i] = i;
1746+
1747+ if (table->file->check_if_supported_inplace_alter(table, &ha_alter_info) ==
1748+ HA_ALTER_INPLACE_NOT_SUPPORTED)
1749+ DBUG_RETURN(-1);
1750+
1751+ if (table->file->ha_prepare_inplace_alter_table(table, &ha_alter_info) ||
1752+ table->file->ha_inplace_alter_table(table, &ha_alter_info) ||
1753+ table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, true))
1754+ {
1755+ table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, false);
1756+ DBUG_RETURN(-1);
1757+ }
1758+
1759+ DBUG_RETURN(0);
1760+}
1761+
1762 /**
1763 Alter table
1764
1765@@ -8067,18 +8261,39 @@
1766 */
1767 if (!(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
1768 {
1769+
1770+ /*
1771+ Check if we can temporarily remove secondary indexes from the table
1772+ before copying the data and recreate them later to utilize InnoDB fast
1773+ index creation.
1774+ TODO: is there a better way to check for InnoDB?
1775+ */
1776+ bool optimize_keys= (alter_info->delayed_key_count > 0) &&
1777+ !my_strcasecmp(system_charset_info,
1778+ new_table->file->table_type(), "InnoDB");
1779 new_table->next_number_field=new_table->found_next_number_field;
1780 THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
1781 DBUG_EXECUTE_IF("abort_copy_table", {
1782 my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
1783 goto err_new_table_cleanup;
1784 });
1785+
1786+ if (optimize_keys)
1787+ {
1788+ /* ignore the error */
1789+ remove_secondary_keys(thd, create_info, new_table, alter_info);
1790+ }
1791+
1792 if (copy_data_between_tables(table, new_table,
1793 alter_info->create_list, ignore,
1794 order_num, order, &copied, &deleted,
1795 alter_info->keys_onoff,
1796 &alter_ctx))
1797 goto err_new_table_cleanup;
1798+
1799+ if (optimize_keys)
1800+ if (restore_secondary_keys(thd, create_info, new_table, alter_info))
1801+ goto err_new_table_cleanup;
1802 }
1803 else
1804 {
1805
1806=== modified file 'Percona-Server/sql/sys_vars.cc'
1807--- Percona-Server/sql/sys_vars.cc 2012-12-04 08:24:59 +0000
1808+++ Percona-Server/sql/sys_vars.cc 2013-01-25 11:48:25 +0000
1809@@ -1270,6 +1270,14 @@
1810 ON_CHECK(event_scheduler_check), ON_UPDATE(event_scheduler_update));
1811 #endif
1812
1813+static Sys_var_mybool Sys_expand_fast_index_creation(
1814+ "expand_fast_index_creation",
1815+ "Enable/disable improvements to the InnoDB fast index creation "
1816+ "functionality. Has no effect when fast index creation is disabled with "
1817+ "the fast-index-creation option",
1818+ SESSION_VAR(expand_fast_index_creation), CMD_LINE(OPT_ARG),
1819+ DEFAULT(FALSE));
1820+
1821 static Sys_var_ulong Sys_expire_logs_days(
1822 "expire_logs_days",
1823 "If non-zero, binary logs will be purged after expire_logs_days "
1824
1825=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
1826--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2012-12-17 22:22:38 +0000
1827+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-01-25 11:48:25 +0000
1828@@ -31,6 +31,8 @@
1829 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
1830
1831 *****************************************************************************/
1832+
1833+#define MYSQL_SERVER
1834
1835 #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
1836 // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
1837@@ -1245,6 +1247,18 @@
1838 }
1839 }
1840
1841+/******************************************************************//**
1842+Returns true if expand_fast_index_creation is enabled for the current
1843+session.
1844+@return the value of the server's expand_fast_index_creation variable */
1845+ibool
1846+thd_expand_fast_index_creation(
1847+/*================================*/
1848+ void* thd)
1849+{
1850+ return((ibool) (((THD*) thd)->variables.expand_fast_index_creation));
1851+}
1852+
1853 /********************************************************************//**
1854 Obtain the InnoDB transaction of a MySQL thread.
1855 @return reference to transaction pointer */
1856
1857=== modified file 'Percona-Server/storage/innobase/handler/handler0alter.cc'
1858--- Percona-Server/storage/innobase/handler/handler0alter.cc 2012-12-04 08:24:59 +0000
1859+++ Percona-Server/storage/innobase/handler/handler0alter.cc 2013-01-25 11:48:25 +0000
1860@@ -2968,6 +2968,8 @@
1861
1862 ut_a(trx->lock.n_active_thrs == 0);
1863
1864+ DBUG_EXECUTE_IF("crash_innodb_add_index_after", DBUG_SUICIDE(););
1865+
1866 error_handling:
1867 /* After an error, remove all those index definitions from the
1868 dictionary which were defined. */
1869
1870=== modified file 'Percona-Server/storage/innobase/include/ha_prototypes.h'
1871--- Percona-Server/storage/innobase/include/ha_prototypes.h 2012-10-16 06:21:51 +0000
1872+++ Percona-Server/storage/innobase/include/ha_prototypes.h 2013-01-25 11:48:25 +0000
1873@@ -533,6 +533,16 @@
1874 /*=================*/
1875 int error_code); /*!< in: MySQL error code */
1876
1877+/******************************************************************//**
1878+Returns true if innodb_expand_fast_index_creation is enabled for the current
1879+session.
1880+@return the value of the server's innodb_expand_fast_index_creation variable */
1881+
1882+ibool
1883+thd_expand_fast_index_creation(
1884+/*===========================*/
1885+ void* thd); /*!< in: thread handle (THD*) */
1886+
1887 /*********************************************************************//**
1888 Compute the next autoinc value.
1889

Subscribers

People subscribed via source and target branches