Commit dc6a0171 authored by Daniel Black's avatar Daniel Black

MDEV-27882 Innodb - recognise MySQL-8.0 innodb flags and give a specific error message

Per fsp0types.h, SDI is on tablespace flags position 14 where MariaDB
stores its pagesize. Flag at position 13, also in MariaDB pagesize
flags, is a MySQL encryption flag.

These are checked only if fsp_flags_is_valid fails, so valid MariaDB
pages sizes don't become errors.

The error message "Cannot reset LSNs in table" was rather specific and
not always true to replaced with more generic error.

ALTER TABLE tbl IMPORT TABLESPACE now reports Unsupported on MySQL
tablespace (rather than index corrupted) along with a server error
message.

MySQL innodb Errors are with with UNSUPPORTED rather than CORRUPTED
to avoid user anxiety.

Reviewer: Marko Mäkelä
parent 0235a528
......@@ -9,5 +9,5 @@ DROP TABLE src;
CREATE TABLE dst (pk INT PRIMARY KEY, value INT) ENGINE=INNODB;
ALTER TABLE dst DISCARD TABLESPACE;
ALTER TABLE dst IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`dst` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`dst` : Data structure corruption
DROP TABLE dst;
......@@ -38,7 +38,7 @@ tab InnoDB # Compact # # # # # # NULL # NULL NULL latin1_swedish_ci NULL 0 N
ALTER TABLE tab DISCARD TABLESPACE;
call mtr.add_suppression("InnoDB: Tried to read .* bytes at offset 0");
ALTER TABLE tab IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`tab` : I/O error
ERROR HY000: Internal error: Error importing tablespace for table `test`.`tab` : I/O error
ALTER TABLE tab IMPORT TABLESPACE;
SELECT * FROM tab;
a
......
......@@ -795,3 +795,19 @@ DROP DATABASE testdb_wl5522;
call mtr.add_suppression("Got error -1 when reading table '.*'");
call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*");
call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded");
#
# MDEV-27882 Innodb - recognise MySQL-8.0 innodb flags and give a specific error message
#
#
CREATE TABLE `t1` (`i` int(11) NOT NULL, PRIMARY KEY (`i`) ) ENGINE=InnoDB;
FLUSH TABLES t1 FOR EXPORT;
backup: t1
UNLOCK TABLES;
ALTER TABLE t1 DISCARD TABLESPACE;
call mtr.add_suppression("InnoDB: unsupported MySQL tablespace");
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Unsupported
DROP TABLE t1;
#
# End of 10.3 tests
#
......@@ -448,7 +448,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,ib_import_reset_space_and_lsn_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Too many concurrent transactions
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Too many concurrent transactions
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug=@saved_debug_dbug;
SET SESSION debug_dbug="+d,ib_import_open_tablespace_failure";
......@@ -873,7 +873,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,ib_import_trigger_corruption_1";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Data structure corruption
SET SESSION debug_dbug=@saved_debug_dbug;
DROP TABLE t1;
unlink: t1.ibd
......@@ -885,7 +885,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,buf_page_import_corrupt_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Data structure corruption
SET SESSION debug_dbug=@saved_debug_dbug;
DROP TABLE t1;
unlink: t1.ibd
......@@ -957,7 +957,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Data structure corruption
SET SESSION debug_dbug=@saved_debug_dbug;
DROP TABLE t1;
unlink: t1.ibd
......
......@@ -3,7 +3,8 @@
#
# FIXME: Unlike MySQL, maybe MariaDB should not read the .ibd files
# of tables with .isl file or DATA DIRECTORY attribute.
call mtr.add_suppression("\\[ERROR\\] InnoDB: Invalid flags 0x7a207879 in .*td\\.ibd");
call mtr.add_suppression("\\[ERROR\\] InnoDB: MySQL-8\\.0 tablespace in ");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Restart in MySQL for migration/recovery\\.");
# FIXME: This is much more noisy than MariaDB 10.1!
call mtr.add_suppression("\\[ERROR\\] InnoDB: Operating system error number .* in a file operation\\.");
call mtr.add_suppression("\\[ERROR\\] InnoDB: The error means the system cannot find the path specified\\.");
......@@ -39,3 +40,10 @@ Warning 1210 innodb_buffer_pool_size must be at least MIN_VAL for innodb_page_si
Error 1231 Variable 'innodb_buffer_pool_size' can't be set to the value of 'WRONG_VALUE'
EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size);
SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig;
#
# MDEV-27882 Innodb - recognise MySQL-8.0 innodb flags and give a specific error message
#
FOUND 1 /InnoDB: MySQL-8\.0 tablespace in \./ibdata1/ in attempted_start.err
#
# End of 10.3 tests
#
......@@ -932,3 +932,34 @@ call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tabl
--remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd
--remove_file $MYSQLTEST_VARDIR/tmp/t1_fk.cfg
--remove_file $MYSQLTEST_VARDIR/tmp/t1_fk.ibd
--echo #
--echo # MDEV-27882 Innodb - recognise MySQL-8.0 innodb flags and give a specific error message
--echo #
--echo #
CREATE TABLE `t1` (`i` int(11) NOT NULL, PRIMARY KEY (`i`) ) ENGINE=InnoDB;
FLUSH TABLES t1 FOR EXPORT;
# We use the cfg file of ours.
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_backup_tablespaces("test", "t1");
EOF
UNLOCK TABLES;
ALTER TABLE t1 DISCARD TABLESPACE;
--move_file $MYSQLTEST_VARDIR/tmp/t1.cfg $MYSQLD_DATADIR/test/t1.cfg
--copy_file std_data/mysql80/t1.ibd $MYSQLD_DATADIR/test/t1.ibd
call mtr.add_suppression("InnoDB: unsupported MySQL tablespace");
--error ER_INTERNAL_ERROR
ALTER TABLE t1 IMPORT TABLESPACE;
DROP TABLE t1;
--remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd
--echo #
--echo # End of 10.3 tests
--echo #
......@@ -15,7 +15,9 @@ let page_size= `select @@innodb_page_size`;
--echo # FIXME: Unlike MySQL, maybe MariaDB should not read the .ibd files
--echo # of tables with .isl file or DATA DIRECTORY attribute.
call mtr.add_suppression("\\[ERROR\\] InnoDB: Invalid flags 0x7a207879 in .*td\\.ibd");
call mtr.add_suppression("\\[ERROR\\] InnoDB: MySQL-8\\.0 tablespace in ");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Restart in MySQL for migration/recovery\\.");
--echo # FIXME: This is much more noisy than MariaDB 10.1!
call mtr.add_suppression("\\[ERROR\\] InnoDB: Operating system error number .* in a file operation\\.");
call mtr.add_suppression("\\[ERROR\\] InnoDB: The error means the system cannot find the path specified\\.");
......@@ -47,7 +49,7 @@ die unless open OUT, ">", "$ENV{datadir}/test/tc.ibd";
print OUT "bar " x $ENV{page_size};
close OUT or die;
die unless open OUT, ">", "$ENV{MYSQL_TMP_DIR}/test/td.ibd";
print OUT "xyz " x $ENV{page_size};
print OUT "Xyz " x $ENV{page_size};
close OUT or die;
EOF
......@@ -101,3 +103,60 @@ EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size
--source include/wait_condition.inc
SET GLOBAL innodb_buffer_pool_size = @innodb_buffer_pool_size_orig;
--echo #
--echo # MDEV-27882 Innodb - recognise MySQL-8.0 innodb flags and give a specific error message
--echo #
--let MYSQLD_DATADIR= `SELECT @@datadir`
--let SERVER_ID= `SELECT @@server_id`
--let EXPECT_FILE_NAME= $MYSQLTEST_VARDIR/tmp/mysqld.$SERVER_ID.expect
--source include/shutdown_mysqld.inc
--move_file $MYSQLD_DATADIR/ibdata1 $MYSQLD_DATADIR/ibdata1.bak
--copy_file std_data/mysql80/ibdata1_$page_size $MYSQLD_DATADIR/ibdata1
perl;
use IO::Handle;
my $size = 9 * 1048576;
if ($ENV{MTR_COMBINATION_32K}) {
$size *= 2;
}
if ($ENV{MTR_COMBINATION_64K}) {
$size *= 4;
}
$size -= $ENV{page_size};
die unless open(FILE, ">>", "$ENV{MYSQLD_DATADIR}/ibdata1");
binmode FILE;
print FILE chr(0) x $size;
close(FILE);
EOF
--let ibdata_size='9M'
if ($MTR_COMBINATION_32K)
{
--let ibdata_size='18M'
}
if ($MTR_COMBINATION_64K)
{
--let ibdata_size='36M'
}
--error 1
exec $MYSQLD --no-defaults --skip-networking --innodb_data_file_path=ibdata1:$ibdata_size --innodb-page-size=$page_size --datadir=$MYSQLD_DATADIR --log-error=$MYSQL_TMP_DIR/attempted_start.err;
let SEARCH_FILE= $MYSQL_TMP_DIR/attempted_start.err;
let SEARCH_PATTERN= InnoDB: MySQL-8\.0 tablespace in \./ibdata1;
source include/search_pattern_in_file.inc;
--remove_file $MYSQL_TMP_DIR/attempted_start.err
--remove_file $MYSQLD_DATADIR/ibdata1
--move_file $MYSQLD_DATADIR/ibdata1.bak $MYSQLD_DATADIR/ibdata1
--source include/start_mysqld.inc
--echo #
--echo # End of 10.3 tests
--echo #
......@@ -78,7 +78,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,ib_import_reset_space_and_lsn_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Too many concurrent transactions
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Too many concurrent transactions
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug=@saved_debug_dbug;
SET SESSION debug_dbug="+d,ib_import_open_tablespace_failure";
......@@ -322,7 +322,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,ib_import_trigger_corruption_1";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Data structure corruption
SET SESSION debug_dbug=@saved_debug_dbug;
DROP TABLE t1;
unlink: t1.ibd
......@@ -335,7 +335,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,buf_page_import_corrupt_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Data structure corruption
SET SESSION debug_dbug=@saved_debug_dbug;
DROP TABLE t1;
unlink: t1.ibd
......@@ -413,7 +413,7 @@ ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
ERROR HY000: Internal error: Error importing tablespace for table `test`.`t1` : Data structure corruption
SET SESSION debug_dbug=@saved_debug_dbug;
DROP TABLE t1;
unlink: t1.ibd
......
......@@ -29,6 +29,7 @@ Created 2013-7-26 by Kevin Lewis
#include "os0file.h"
#include "page0page.h"
#include "srv0start.h"
#include "log.h"
/** Initialize the name, size and order of this datafile
@param[in] name tablespace name, will be copied
......@@ -346,10 +347,23 @@ Datafile::read_first_page(bool read_only_mode)
if (!fsp_flags_is_valid(m_flags, m_space_id)) {
ulint cflags = fsp_flags_convert_from_101(m_flags);
if (cflags == ULINT_UNDEFINED) {
ib::error()
<< "Invalid flags " << ib::hex(m_flags)
<< " in " << m_filepath;
return(DB_CORRUPTION);
switch (fsp_flags_is_incompatible_mysql(m_flags)) {
case 0:
sql_print_error("InnoDB: Invalid flags 0x%zx in %s",
m_flags, m_filepath);
return(DB_CORRUPTION);
case 3:
case 2:
sql_print_error("InnoDB: MySQL-8.0 tablespace in %s",
m_filepath);
break;
case 1:
sql_print_error("InnoDB: MySQL Encrypted tablespace in %s",
m_filepath);
break;
}
sql_print_error("InnoDB: Restart in MySQL for migration/recovery.");
return(DB_UNSUPPORTED);
} else {
m_flags = cflags;
}
......
......@@ -755,6 +755,20 @@ fsp_flags_match(ulint expected, ulint actual)
return(actual == expected);
}
/** Determine if FSP_SPACE_FLAGS are from an incompatible MySQL format.
@param flags the contents of FSP_SPACE_FLAGS
@return MySQL flags shifted.
@retval 0, if not a MySQL incompatible format. */
MY_ATTRIBUTE((warn_unused_result, const))
inline ulint fsp_flags_is_incompatible_mysql(ulint flags)
{
/*
MySQL-8.0 SDI flag (bit 14),
or MySQL 5.7 Encyption flag (bit 13)
*/
return flags >> 13 & 3;
}
/** Calculates the descriptor index within a descriptor page.
@param[in] page_size page size
@param[in] offset page offset
......
......@@ -46,6 +46,7 @@ Created 2012-02-08 by Sunny Bains.
#ifdef HAVE_SNAPPY
#include "snappy-c.h"
#endif
#include "log.h"
#include <vector>
......@@ -571,9 +572,15 @@ AbstractCallback::init(
if (!fsp_flags_is_valid(m_space_flags, true)) {
ulint cflags = fsp_flags_convert_from_101(m_space_flags);
if (cflags == ULINT_UNDEFINED) {
ib::error() << "Invalid FSP_SPACE_FLAGS="
<< ib::hex(m_space_flags);
return(DB_CORRUPTION);
switch (fsp_flags_is_incompatible_mysql(m_space_flags)) {
case 0:
sql_print_error("InnoDB: Invalid FSP_SPACE_FLAGS=0x%zx",
m_space_flags);
return(DB_CORRUPTION);
default:
sql_print_error("InnoDB: unsupported MySQL tablespace");
return(DB_UNSUPPORTED);
}
}
m_space_flags = cflags;
}
......@@ -4171,7 +4178,7 @@ row_import_for_mysql(
ib_errf(trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_INTERNAL_ERROR,
"Cannot reset LSNs in table %s : %s",
"Error importing tablespace for table %s : %s",
table_name, ut_strerr(err));
}
......
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