Commit 0a190b6b authored by Michael Widenius's avatar Michael Widenius

Fixed lp:944422 "mysql_upgrade destroys Maria tables?"

The issue was that check/optimize/anaylze did not zerofill the table before they started to work on it.
Added one more element to not often used function handler::auto_repair() to allow handler to decide when to auto repair.


mysql-test/suite/maria/r/maria-autozerofill.result:
  Test case for lp:944422
mysql-test/suite/maria/t/maria-autozerofill.test:
  Test case for lp:944422
sql/ha_partition.cc:
  Added argument to auto_repair()
sql/ha_partition.h:
  Added argument to auto_repair()
sql/handler.h:
  Added argument to auto_repair()
sql/table.cc:
  Let auto_repair() decide which errors to trigger auto-repair
storage/archive/ha_archive.h:
  Added argument to auto_repair()
storage/csv/ha_tina.h:
  Added argument to auto_repair()
storage/maria/ha_maria.cc:
  Give better error & warning messages for auto-repaired tables.
storage/maria/ha_maria.h:
  Added argument to auto_repair()
  Always auto-repair in case of moved table.
storage/maria/ma_open.c:
  Remove special handling of HA_ERR_OLD_FILE (this is now handled in auto_repair())
storage/myisam/ha_myisam.h:
  Added argument to auto_repair()
parent 98d5695a
......@@ -4,18 +4,43 @@ create database mysqltest;
use mysqltest;
create table t1(a int) engine=maria;
insert into t1 values(1);
flush table t1;
create table t2 (a int) engine=maria;
INSERT INTO t2 VALUES (1),(2);
create table t3 (a int) engine=maria;
INSERT INTO t3 VALUES (1),(2);
create table t4 (a int) engine=maria;
INSERT INTO t4 VALUES (1),(2);
flush tables;
create_rename_lsn has non-magic value
* shut down mysqld, removed logs, restarted it
select * from t1;
a
1
Warnings:
Error 1194 t1' is marked as crashed and should be repaired
Note 1194 Zerofilling moved table ./mysqltest/t1
flush table t1;
Status: changed,sorted index pages,zerofilled,movable
create_rename_lsn has magic value
insert into t1 values(2);
flush table t1;
create_rename_lsn has non-magic value
check table t2;
Table Op Msg_type Msg_text
mysqltest.t2 check error Table is from another system and must be zerofilled or repaired to be usable on this system
mysqltest.t2 check error Corrupt
check table t2;
Table Op Msg_type Msg_text
mysqltest.t2 check error Table is from another system and must be zerofilled or repaired to be usable on this system
mysqltest.t2 check error Corrupt
repair table t2;
Table Op Msg_type Msg_text
mysqltest.t2 repair status OK
optimize table t3;
Table Op Msg_type Msg_text
mysqltest.t3 optimize Note Zerofilling moved table ./mysqltest/t3
mysqltest.t3 optimize status OK
analyze table t4;
Table Op Msg_type Msg_text
mysqltest.t4 analyze Note Zerofilling moved table ./mysqltest/t4
mysqltest.t4 analyze status OK
drop database mysqltest;
......@@ -22,9 +22,17 @@ connection default;
use mysqltest;
--enable_reconnect
# Create some tables for future tests
create table t1(a int) engine=maria;
insert into t1 values(1);
flush table t1;
create table t2 (a int) engine=maria;
INSERT INTO t2 VALUES (1),(2);
create table t3 (a int) engine=maria;
INSERT INTO t3 VALUES (1),(2);
create table t4 (a int) engine=maria;
INSERT INTO t4 VALUES (1),(2);
flush tables;
# Check that table is not zerofilled, not movable
let $MYSQLD_DATADIR= `select @@datadir`;
--exec $MARIA_CHK -dv $MYSQLD_DATADIR/mysqltest/t1 >$MYSQLTEST_VARDIR/tmp/mariachk.txt
......@@ -80,4 +88,14 @@ perl;
close FILE;
EOF
#
# BUG#44422 "mysql_upgrade destroys Maria tables?"
# Check repair and optimize of moved table
#
check table t2;
check table t2;
repair table t2;
optimize table t3;
analyze table t4;
drop database mysqltest;
......@@ -1223,7 +1223,7 @@ bool ha_partition::check_and_repair(THD *thd)
@retval FALSE Cannot be auto repaired
*/
bool ha_partition::auto_repair() const
bool ha_partition::auto_repair(int error) const
{
DBUG_ENTER("ha_partition::auto_repair");
......@@ -1231,7 +1231,7 @@ bool ha_partition::auto_repair() const
As long as we only support one storage engine per table,
we can use the first partition for this function.
*/
DBUG_RETURN(m_file[0]->auto_repair());
DBUG_RETURN(m_file[0]->auto_repair(error));
}
......
......@@ -1105,7 +1105,7 @@ class ha_partition :public handler
virtual int check(THD* thd, HA_CHECK_OPT *check_opt);
virtual int repair(THD* thd, HA_CHECK_OPT *check_opt);
virtual bool check_and_repair(THD *thd);
virtual bool auto_repair() const;
virtual bool auto_repair(int error) const;
virtual bool is_crashed() const;
private:
......
......@@ -1668,7 +1668,7 @@ class handler :public Sql_alloc
virtual bool low_byte_first() const { return 1; }
virtual uint checksum() const { return 0; }
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
virtual bool auto_repair(int error) const { return 0; }
#define CHF_CREATE_FLAG 0
#define CHF_DELETE_FLAG 1
......
......@@ -1929,8 +1929,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
{
/* Set a flag if the table is crashed and it can be auto. repaired */
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
outparam->file->auto_repair() &&
share->crashed= (outparam->file->auto_repair(ha_err) &&
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
switch (ha_err)
......
......@@ -125,7 +125,9 @@ class ha_archive: public handler
int free_share();
int init_archive_writer();
int init_archive_reader();
bool auto_repair() const { return 1; } // For the moment we just do this
// Always try auto_repair in case of HA_ERR_CRASHED_ON_USAGE
bool auto_repair(int error) const
{ return error == HA_ERR_CRASHED_ON_USAGE; }
int read_data_header(azio_stream *file_to_read);
void position(const uchar *record);
int info(uint);
......
......@@ -151,6 +151,8 @@ class ha_tina: public handler
int rnd_end();
int repair(THD* thd, HA_CHECK_OPT* check_opt);
/* This is required for SQL layer to know that we support autorepair */
bool auto_repair(int error) const
{ return error == HA_ERR_CRASHED_ON_USAGE; }
bool auto_repair() const { return 1; }
void position(const uchar *record);
int info(uint);
......
......@@ -52,6 +52,9 @@ C_MODE_END
ulong pagecache_division_limit, pagecache_age_threshold;
ulonglong pagecache_buffer_size;
const char *zerofill_error_msg=
"Table is from another system and must be zerofilled or repaired to be "
"usable on this system";
/**
As the auto-repair is initiated when opened from the SQL layer
......@@ -972,7 +975,15 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
}
if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
{
if (my_errno == HA_ERR_OLD_FILE)
{
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_CRASHED_ON_USAGE,
zerofill_error_msg);
}
return (my_errno ? my_errno : -1);
}
file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref;
......@@ -1074,6 +1085,13 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
return HA_ADMIN_ALREADY_DONE;
maria_chk_init_for_check(&param, file);
if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) ==
STATE_MOVED)
{
_ma_check_print_error(&param, zerofill_error_msg);
return HA_ADMIN_CORRUPT;
}
(void) maria_chk_status(&param, file); // Not fatal
error= maria_chk_size(&param, file);
if (!error)
......@@ -2024,6 +2042,11 @@ bool ha_maria::check_and_repair(THD *thd)
if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) ==
STATE_MOVED)
{
/* Remove error about crashed table */
mysql_reset_errors(thd, true);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_CRASHED_ON_USAGE,
"Zerofilling moved table %s", table->s->path.str);
sql_print_information("Zerofilling moved table: '%s'",
table->s->path.str);
if (!(error= zerofill(thd, &check_opt)))
......
......@@ -142,8 +142,14 @@ class ha_maria :public handler
bool check_and_repair(THD * thd);
bool is_crashed() const;
bool is_changed() const;
bool auto_repair() const
{ return test(maria_recover_options & HA_RECOVER_ANY); }
bool auto_repair(int error) const
{
/* Always auto-repair moved tables (error == HA_ERR_OLD_FILE) */
return ((test(maria_recover_options & HA_RECOVER_ANY) &&
error == HA_ERR_CRASHED_ON_USAGE) ||
error == HA_ERR_OLD_FILE);
}
int optimize(THD * thd, HA_CHECK_OPT * check_opt);
int restore(THD * thd, HA_CHECK_OPT * check_opt);
int backup(THD * thd, HA_CHECK_OPT * check_opt);
......
......@@ -968,8 +968,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
tmp_name.length= strlen(name);
_ma_report_error(save_errno, &tmp_name);
}
if (save_errno == HA_ERR_OLD_FILE) /* uuid is different ? */
save_errno= HA_ERR_CRASHED_ON_USAGE; /* the code to trigger auto-repair */
switch (errpos) {
case 5:
if (data_file >= 0)
......
......@@ -128,7 +128,11 @@ class ha_myisam: public handler
int repair(THD* thd, HA_CHECK_OPT* check_opt);
bool check_and_repair(THD *thd);
bool is_crashed() const;
bool auto_repair() const { return myisam_recover_options != 0; }
bool auto_repair(int error) const
{
return (myisam_recover_options != 0 &&
error == HA_ERR_CRASHED_ON_USAGE);
}
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
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