Tables are lost for DDL and different behaviors for alter tablefailed situation between innobase and

Tables are lost for DDL and different behaviors for alter tablefailed situation between innobase and

am 11.08.2011 12:56:59 von hiu

--0015175cdac0ecbf2004aa38a7f7
Content-Type: text/plain; charset=ISO-8859-1

*summary:*

Recently we hit lost tables during DDL for online products, and after some
observersion, we found some interesting hehaviors if fil_rename_tablespace
failed as retry > 250000.
That might be another issue that not discussed here.
THERE MUST BE SINGLE TABLESPACE

Here is the steps to show the behavior:

*1. compile 5.1.48 source code.*

CFLAGS="-O0 -g" CXX=gcc CXXFLAGS="-O0 -g -felide-constructors \
-fno-exceptions -fno-rtti"

export CFLAGS CXXFLAGS

../configure --with-plugins=innodb_plugin

make -j32



*2. debug with plugin innodb*
2.1 # attach a running pid
(gdb) b fil_rename_tablespace
Breakpoint 1 at 0x2aaaaabfed30: file fil/fil0fil.c, line 2435.
(gdb) c
Continuing.
[Switching to Thread 0x4944a940 (LWP 7069)]

Breakpoint 1, fil_rename_tablespace (old_name=0xeacdc20 "sbtest/sb1", id=51,
new_name=0xea96fa0 "sbtest/#sql2-1b8b-1") at fil/fil0fil.c:2435
2435 {
(gdb) c
Continuing.

Breakpoint 1, fil_rename_tablespace (old_name=0xeabb3f0
"sbtest/#sql-1b8b_1", id=52, new_name=0xea96fa0 "sbtest/sb1") at
fil/fil0fil.c:2435
2435 {
(gdb) return 0
Make fil_rename_tablespace return now? (y or n) y
#0 0x00002aaaaabea8c4 in dict_table_rename_in_cache (table=0xeabb288,
new_name=0xea96fa0 "sbtest/sb1",
rename_also_foreigns=1) at dict/dict0dict.c:951
951 } else if (!fil_rename_tablespace(old_name,
table->space,
(gdb)

(gdb) l
946 fputs(" (", stderr);
947 ut_print_filename(stderr,
948
table->dir_path_of_temp_table);
949 fputs(" )\n", stderr);
950 return(FALSE);
951 } else if (!fil_rename_tablespace(old_name,
table->space,
952 new_name)) {
953 return(FALSE);
954 }
955 }
(gdb) finish
Run till exit from #0 0x00002aaaaabea8c4 in dict_table_rename_in_cache
(table=0xeabb288, new_name=0xea96fa0 "sbtest/sb1", rename_also_foreigns=1)
at dict/dict0dict.c:951
0x00002aaaaac6527e in row_rename_table_for_mysql (old_name=0xea97000
"sbtest/#sql-1b8b_1", new_name=0xea96fa0 "sbtest/sb1", trx=0xeacf728,
commit=1)
at row/row0mysql.c:3905
3905 if (!dict_table_rename_in_cache(table, new_name,
Value returned is $1 = 0
(gdb) l
3900 trx->error_state = DB_SUCCESS;
3901 } else {
3902 /* The following call will also rename the .ibd data
file if
3903 the table is stored in a single-table tablespace */
3904
3905 if (!dict_table_rename_in_cache(table, new_name,
3906 !new_is_tmp)) {
3907 trx->error_state = DB_SUCCESS;
3908 trx_general_rollback_for_mysql(trx, NULL);
3909 trx->error_state = DB_SUCCESS;
(gdb) l
3910 goto funct_exit;
3911 }
3912
3913 /* We only want to switch off some of the type
checking in
3914 an ALTER, not in a RENAME. */
3915
3916 err = dict_load_foreigns(
3917 new_name, !old_is_tmp ||
trx->check_foreigns);
3918
3919 if (err != DB_SUCCESS) {
(gdb) finish
Run till exit from #0 0x00002aaaaac6527e in row_rename_table_for_mysql
(old_name=0xea97000 "sbtest/#sql-1b8b_1", new_name=0xea96fa0 "sbtest/sb1",
trx=0xeacf728, commit=1) at row/row0mysql.c:3905
0x00002aaaaac14e0b in ha_innodb::rename_table () from
/u01/mysql-5.1.48/storage/innodb_plugin/.libs/ha_innodb_plug in.so
Value returned is $2 = 10


2.2 here is the key routines:
storage/innodb_plugin/row/row0mysql.c: row_rename_table_for_mysql
3905 if (!dict_table_rename_in_cache(table, new_name,
3906 !new_is_tmp)) {
3907 trx->error_state = DB_SUCCESS;
3908 trx_general_rollback_for_mysql(trx, NULL);
3909 trx->error_state = DB_SUCCESS;
3910 goto funct_exit;
3911 }


2.3 client's output:
root@sbtest 05:00:24>alter table sb1 add column d2 int;
Query OK, 0 rows affected (9 min 47.97 sec)
Records: 0 Duplicates: 0 Warnings: 0

root@sbtest 05:11:26>desc sb1;
ERROR 1146 (42S02): Table 'sbtest.sb1' doesn't exist



*3. different code between innodb and plugin*

3.1 innodb add err = DB_ERROR; before goto funct_exit; when
dict_table_rename_in_cache failed.

3.2 test innodb work and result could be refered to modified innodb plugin
just like innobase behavior, add err = DB_ERROR; before exit

3905 if (!dict_table_rename_in_cache(table, new_name,
3906 !new_is_tmp)) {
3907 trx->error_state = DB_SUCCESS;
3908 trx_general_rollback_for_mysql(trx, NULL);
3909 trx->error_state = DB_SUCCESS;
3910 err = DB_ERROR;
3911 goto funct_exit;
3912 }


3.3 re-debug with modified innodb plugin

Breakpoint 1, fil_rename_tablespace (old_name=0x15b19620 "sbtest/sb2",
id=53, new_name=0x15b26250 "sbtest/#sql2-1eb9-1") at fil/fil0fil.c:2435
2435 {
(gdb) c
Continuing.

Breakpoint 1, fil_rename_tablespace (old_name=0x15ae4600
"sbtest/#sql-1eb9_1", id=54, new_name=0x15b26250 "sbtest/sb2") at
fil/fil0fil.c:2435
2435 {
(gdb) return 0
Make fil_rename_tablespace return now? (y or n) y
#0 0x00002aaaaabea8c4 in dict_table_rename_in_cache (table=0x15ae4498,
new_name=0x15b26250 "sbtest/sb2",
rename_also_foreigns=1) at dict/dict0dict.c:951
951 } else if (!fil_rename_tablespace(old_name,
table->space,
(gdb) finish
Run till exit from #0 0x00002aaaaabea8c4 in dict_table_rename_in_cache
(table=0x15ae4498, new_name=0x15b26250 "sbtest/sb2", rename_also_foreigns=1)
at dict/dict0dict.c:951
0x00002aaaaac6527e in row_rename_table_for_mysql (old_name=0x15b1a7a0
"sbtest/#sql-1eb9_1", new_name=0x15b26250 "sbtest/sb2", trx=0x15b25998,
commit=1)
at row/row0mysql.c:3905
3905 if (!dict_table_rename_in_cache(table, new_name,
Value returned is $1 = 0
(gdb) finish
Run till exit from #0 0x00002aaaaac6527e in row_rename_table_for_mysql
(old_name=0x15b1a7a0 "sbtest/#sql-1eb9_1", new_name=0x15b26250 "sbtest/sb2",
trx=0x15b25998, commit=1) at row/row0mysql.c:3905
0x00002aaaaac14e0b in ha_innodb::rename_table () from
/u01/mysql-5.1.48/storage/innodb_plugin/.libs/ha_innodb_plug in.so
Value returned is $2 = 11
(gdb) c
Continuing.

Breakpoint 1, fil_rename_tablespace (old_name=0x15b19770
"sbtest/#sql2-1eb9-1", id=53, new_name=0x15b1a7a0 "sbtest/sb2") at
fil/fil0fil.c:2435
2435 {
(gdb) c
Continuing.
c

3.4 client's output

root@sbtest 05:15:17>create table sb2 (a int);
Query OK, 0 rows affected (0.01 sec)

root@sbtest 05:15:20>alter table sb2 add column d2 int;
ERROR 1025 (HY000): Error on rename of './sbtest/#sql-1eb9_1' to
'./sbtest/sb2' (errno: -1)
root@sbtest 05:16:28>

*4. question:*
why removed the err=DB_ERROR? It's a defect or intention?

--0015175cdac0ecbf2004aa38a7f7--