Commit 623a2254 authored by MySQL Build Team's avatar MySQL Build Team

Backport into build-201102032246-5.1.52sp1

> ------------------------------------------------------------
> revno: 3452.17.1
> revision-id: mattias.jonsson@oracle.com-20101005125751-ds92svhhb13ds8ri
> parent: sergey.glukhov@sun.com-20101004085126-ia6veky4w6j87i43
> committer: Mattias Jonsson <mattias.jonsson@oracle.com>
> branch nick: b55091-51-security
> timestamp: Tue 2010-10-05 14:57:51 +0200
> message:
>   Bug#55091: Server crashes on ADD PARTITION after a failed attempt
>   
>   In case of failure in ALTER ... PARTITION under LOCK TABLE
>   the server could crash, due to it had modified the locked
>   table object, which was not reverted in case of failure,
>   resulting in a bad table definition used after the failed
>   command.
>   
>   Solved by always closing the LOCKED TABLE, even in case
>   of error.
>   
>   Note: this is a 5.1-only fix, bug#56172 fixed it in 5.5+
parent 13d4da72
call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB internal");
#
# Bug#55091: Server crashes on ADD PARTITION after a failed attempt
#
SET @old_innodb_file_format_check = @@global.innodb_file_format_check;
SET @old_innodb_file_format = @@global.innodb_file_format;
SET @old_innodb_file_per_table = @@global.innodb_file_per_table;
SET @old_innodb_strict_mode = @@global.innodb_strict_mode;
SET @@global.innodb_file_format = Barracuda,
@@global.innodb_file_per_table = ON,
@@global.innodb_strict_mode = ON;
# Connection con1
CREATE TABLE t1 (id INT NOT NULL
PRIMARY KEY,
user_num CHAR(10)
) ENGINE = InnoDB
KEY_BLOCK_SIZE=4
PARTITION BY HASH(id) PARTITIONS 1;
t1#P#p0.ibd
t1.frm
t1.par
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`user_num` char(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=4
/*!50100 PARTITION BY HASH (id)
PARTITIONS 1 */
SET GLOBAL innodb_file_per_table = OFF;
# Connection con2
LOCK TABLE t1 WRITE;
# ALTER fails because COMPRESSED/KEY_BLOCK_SIZE
# are incompatible with innodb_file_per_table = OFF;
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
ERROR HY000: Got error 1478 from storage engine
t1#P#p0.ibd
t1.frm
t1.par
# This SET is not needed to reproduce the bug,
# it is here just to make the test case more realistic
SET innodb_strict_mode = OFF;
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
Warnings:
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4.
t1.frm
t1.par
ALTER TABLE t1 REBUILD PARTITION p0;
Warnings:
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4.
UNLOCK TABLES;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`user_num` char(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=4
/*!50100 PARTITION BY HASH (id)
PARTITIONS 3 */
DROP TABLE t1;
# Connection default
SET @@global.innodb_strict_mode = @old_innodb_strict_mode;
SET @@global.innodb_file_format = @old_innodb_file_format;
SET @@global.innodb_file_per_table = @old_innodb_file_per_table;
SET @@global.innodb_file_format_check = @old_innodb_file_format_check;
SET NAMES utf8; SET NAMES utf8;
CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a))
ENGINE=InnoDB ENGINE=InnoDB
......
--source include/have_partition.inc --source include/have_partition.inc
--source include/have_innodb_plugin.inc --source include/have_innodb_plugin.inc
# Remove the line below when bug#53307 is solved.
--source include/not_valgrind.inc
let $MYSQLD_DATADIR= `SELECT @@datadir`;
call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB internal");
--echo #
--echo # Bug#55091: Server crashes on ADD PARTITION after a failed attempt
--echo #
SET @old_innodb_file_format_check = @@global.innodb_file_format_check;
SET @old_innodb_file_format = @@global.innodb_file_format;
SET @old_innodb_file_per_table = @@global.innodb_file_per_table;
SET @old_innodb_strict_mode = @@global.innodb_strict_mode;
SET @@global.innodb_file_format = Barracuda,
@@global.innodb_file_per_table = ON,
@@global.innodb_strict_mode = ON;
--echo # Connection con1
--connect(con1,localhost,root,,)
CREATE TABLE t1 (id INT NOT NULL
PRIMARY KEY,
user_num CHAR(10)
) ENGINE = InnoDB
KEY_BLOCK_SIZE=4
PARTITION BY HASH(id) PARTITIONS 1;
--list_files $MYSQLD_DATADIR/test
SHOW CREATE TABLE t1;
SET GLOBAL innodb_file_per_table = OFF;
--disconnect con1
--connect(con2,localhost,root,,)
--echo # Connection con2
LOCK TABLE t1 WRITE;
--echo # ALTER fails because COMPRESSED/KEY_BLOCK_SIZE
--echo # are incompatible with innodb_file_per_table = OFF;
--error ER_GET_ERRNO
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
--list_files $MYSQLD_DATADIR/test
--echo # This SET is not needed to reproduce the bug,
--echo # it is here just to make the test case more realistic
SET innodb_strict_mode = OFF;
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
--list_files $MYSQLD_DATADIR/test
# really bug#56172
ALTER TABLE t1 REBUILD PARTITION p0;
UNLOCK TABLES;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--disconnect con2
--connection default
--echo # Connection default
SET @@global.innodb_strict_mode = @old_innodb_strict_mode;
SET @@global.innodb_file_format = @old_innodb_file_format;
SET @@global.innodb_file_per_table = @old_innodb_file_per_table;
SET @@global.innodb_file_format_check = @old_innodb_file_format_check;
# #
# Bug#32430 - show engine innodb status causes errors # Bug#32430 - show engine innodb status causes errors
......
...@@ -5934,6 +5934,12 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) ...@@ -5934,6 +5934,12 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
int err; int err;
if (lpt->thd->locked_tables) if (lpt->thd->locked_tables)
{ {
/*
Close the table if open, to remove/destroy the already altered
table->part_info object, so that it is not reused.
*/
if (lpt->table->db_stat)
abort_and_upgrade_lock_and_close_table(lpt);
/* /*
When we have the table locked, it is necessary to reopen the table When we have the table locked, it is necessary to reopen the table
since all table objects were closed and removed as part of the since all table objects were closed and removed as part of the
...@@ -6436,7 +6442,20 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ...@@ -6436,7 +6442,20 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
table, table_list, FALSE, NULL, table, table_list, FALSE, NULL,
written_bin_log)); written_bin_log));
err: err:
if (thd->locked_tables)
{
/*
table->part_info was altered in prep_alter_part_table and must be
destroyed and recreated, since otherwise it will be reused, since
we are under LOCK TABLE.
*/
alter_partition_lock_handling(lpt);
}
else
{
/* Force the table to be closed to avoid reuse of the table->part_info */
close_thread_tables(thd); close_thread_tables(thd);
}
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment