From 9f85560212241f07b7bdff7df639c0b9a519bed5 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 3 Sep 2010 20:55:56 +0300 Subject: Enable archive tables to work with mysql_upgrade / repair Made long file names from previous patch shorter mysql-test/r/archive.result: Added testing of repair (for upgrade) of 5.0 tables. mysql-test/std_data/archive_5_0.ARM: Archive table created in MySQL 5.0 mysql-test/std_data/archive_5_0.ARZ: Archive table created in MySQL 5.0 mysql-test/std_data/archive_5_0.frm: Archive table created in MySQL 5.0 mysql-test/std_data/long_table_name.MYD: Made long file names shorter mysql-test/std_data/long_table_name.MYI: Made long file names shorter mysql-test/std_data/long_table_name.frm: Made long file names shorter mysql-test/t/archive.test: Added testing of repair (for upgrade) of 5.0 tables. sql/sql_table.cc: Allow recreate to open crashed tables. sql/table.cc: Fix error message if storage engine doesn't exists. storage/archive/azio.c: Reset status values in case archive is of old versions storage/archive/ha_archive.cc: Fix to allow one to open old versions of table during repair Reset status variables for old version tables If the the table is of old version, force upgrade with ALTER TABLE when doing repair storage/archive/ha_archive.h: Added variables to detect old versions --- mysql-test/r/archive.result | 12 +++++- mysql-test/std_data/archive_5_0.ARM | Bin 0 -> 19 bytes mysql-test/std_data/archive_5_0.ARZ | Bin 0 -> 138 bytes mysql-test/std_data/archive_5_0.frm | Bin 0 -> 8578 bytes mysql-test/std_data/long_table_name.MYD | Bin 0 -> 56 bytes mysql-test/std_data/long_table_name.MYI | Bin 0 -> 6144 bytes mysql-test/std_data/long_table_name.frm | Bin 0 -> 8650 bytes ...esarrolloempres?9120761097220077376?cio_com.MYD | Bin 56 -> 0 bytes ...esarrolloempres?9120761097220077376?cio_com.MYI | Bin 6144 -> 0 bytes ...esarrolloempres?9120761097220077376?cio_com.frm | Bin 8650 -> 0 bytes mysql-test/t/archive.test | 13 +++++++ sql/sql_table.cc | 3 ++ sql/table.cc | 3 +- storage/archive/azio.c | 11 ++++++ storage/archive/ha_archive.cc | 42 +++++++++++++++------ storage/archive/ha_archive.h | 3 +- 16 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 mysql-test/std_data/archive_5_0.ARM create mode 100644 mysql-test/std_data/archive_5_0.ARZ create mode 100644 mysql-test/std_data/archive_5_0.frm create mode 100644 mysql-test/std_data/long_table_name.MYD create mode 100644 mysql-test/std_data/long_table_name.MYI create mode 100644 mysql-test/std_data/long_table_name.frm delete mode 100644 mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD delete mode 100644 mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI delete mode 100644 mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index f90bcb521e1..5a731e6476c 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12725,8 +12725,7 @@ INSERT INTO t1 (col1, col2) VALUES (1, "value"); ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! REPAIR TABLE t1; Table Op Msg_type Msg_text -test.t1 repair Error Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! -test.t1 repair error Corrupt +test.t1 repair status OK DROP TABLE t1; # # BUG#48757 - missing .ARZ file causes server crash @@ -12756,3 +12755,12 @@ a 1 2 DROP TABLE t1; +select * from t1; +ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +select sum(length(a)),sum(b) from t1; +sum(length(a)) sum(b) +8670 187 +drop table t1; diff --git a/mysql-test/std_data/archive_5_0.ARM b/mysql-test/std_data/archive_5_0.ARM new file mode 100644 index 00000000000..8f1111437d8 Binary files /dev/null and b/mysql-test/std_data/archive_5_0.ARM differ diff --git a/mysql-test/std_data/archive_5_0.ARZ b/mysql-test/std_data/archive_5_0.ARZ new file mode 100644 index 00000000000..d24e76884cc Binary files /dev/null and b/mysql-test/std_data/archive_5_0.ARZ differ diff --git a/mysql-test/std_data/archive_5_0.frm b/mysql-test/std_data/archive_5_0.frm new file mode 100644 index 00000000000..827213d329d Binary files /dev/null and b/mysql-test/std_data/archive_5_0.frm differ diff --git a/mysql-test/std_data/long_table_name.MYD b/mysql-test/std_data/long_table_name.MYD new file mode 100644 index 00000000000..2ff33451b5f Binary files /dev/null and b/mysql-test/std_data/long_table_name.MYD differ diff --git a/mysql-test/std_data/long_table_name.MYI b/mysql-test/std_data/long_table_name.MYI new file mode 100644 index 00000000000..cffa158beae Binary files /dev/null and b/mysql-test/std_data/long_table_name.MYI differ diff --git a/mysql-test/std_data/long_table_name.frm b/mysql-test/std_data/long_table_name.frm new file mode 100644 index 00000000000..6a812a8b137 Binary files /dev/null and b/mysql-test/std_data/long_table_name.frm differ diff --git a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD b/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD deleted file mode 100644 index 2ff33451b5f..00000000000 Binary files a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD and /dev/null differ diff --git a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI b/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI deleted file mode 100644 index cffa158beae..00000000000 Binary files a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI and /dev/null differ diff --git a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm b/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm deleted file mode 100644 index 6a812a8b137..00000000000 Binary files a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm and /dev/null differ diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 6704257f9af..7478c7dcdce 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1680,3 +1680,16 @@ SELECT * FROM t1; REPAIR TABLE t1 EXTENDED; SELECT * FROM t1; DROP TABLE t1; + +# +# Bug #47012 archive tables are not upgradeable, and server crashes on +# any access +# +copy_file std_data/archive_5_0.frm $MYSQLD_DATADIR/test/t1.frm; +copy_file std_data/archive_5_0.ARZ $MYSQLD_DATADIR/test/t1.ARZ; +copy_file std_data/archive_5_0.ARM $MYSQLD_DATADIR/test/t1.ARM; +--error ER_TABLE_NEEDS_UPGRADE +select * from t1; +repair table t1; +select sum(length(a)),sum(b) from t1; +drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a0621dbbdcf..96be7c4437c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4804,7 +4804,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (check_old_types == HA_ADMIN_NEEDS_ALTER || check_for_upgrade == HA_ADMIN_NEEDS_ALTER) { + /* We use extra_open_options to be able to open crashed tables */ + thd->open_options|= extra_open_options; result_code= admin_recreate_table(thd, table); + thd->open_options= ~extra_open_options; goto send_result; } if (check_old_types || check_for_upgrade) diff --git a/sql/table.cc b/sql/table.cc index a7ed2dd40ff..a3c6f07cddf 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -866,7 +866,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, /* Read extra data segment */ uchar *buff, *next_chunk, *buff_end; DBUG_PRINT("info", ("extra segment size is %u bytes", n_length)); - if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME)))) + if (!(next_chunk= buff= (uchar*) my_malloc(n_length+1, MYF(MY_WME)))) goto err; if (my_pread(file, buff, n_length, record_offset + share->reclength, MYF(MY_NABP))) @@ -945,6 +945,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, { /* purecov: begin inspected */ error= 8; + name.str[name.length]= 0; my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str); my_free(buff, MYF(0)); goto err; diff --git a/storage/archive/azio.c b/storage/archive/azio.c index a24350dd454..fc54d98ab15 100644 --- a/storage/archive/azio.c +++ b/storage/archive/azio.c @@ -150,6 +150,17 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd) } else { + /* Reset values in case of old version of archive file */ + s->rows= 0; + s->forced_flushes= 0; + s->shortest_row= 0; + s->longest_row= 0; + s->auto_increment= 0; + s->check_point= 0; + s->comment_start_pos= 0; + s->comment_length= 0; + s->frm_start_pos= 0; + s->frm_length= 0; check_header(s); /* skip the .az header */ } diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 988337ec50e..d0cb34455b9 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -293,7 +293,7 @@ int ha_archive::read_data_header(azio_stream *file_to_read) DBUG_PRINT("ha_archive", ("Version %u", data_buffer[1])); if ((data_buffer[0] != (uchar)ARCHIVE_CHECK_HEADER) && - (data_buffer[1] != (uchar)ARCHIVE_VERSION)) + (data_buffer[1] == 1 || data_buffer[1] == 2)) DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); DBUG_RETURN(0); @@ -360,9 +360,19 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc) my_free(share, MYF(0)); DBUG_RETURN(NULL); } - stats.auto_increment_value= archive_tmp.auto_increment + 1; - share->rows_recorded= (ha_rows)archive_tmp.rows; - share->crashed= archive_tmp.dirty; + share->version= archive_tmp.version; + if (archive_tmp.version == ARCHIVE_VERSION) + { + stats.auto_increment_value= archive_tmp.auto_increment + 1; + share->rows_recorded= (ha_rows)archive_tmp.rows; + share->crashed= archive_tmp.dirty; + } + else + { + /* Used by repair */ + share->rows_recorded= ~(ha_rows) 0; + stats.auto_increment_value= 0; + } /* If archive version is less than 3, It should be upgraded before use. @@ -512,10 +522,19 @@ int ha_archive::open(const char *name, int mode, uint open_options) case 0: break; case HA_ERR_CRASHED_ON_USAGE: + DBUG_PRINT("ha_archive", ("archive table was crashed")); if (open_options & HA_OPEN_FOR_REPAIR) + { + rc= 0; break; + } /* fall through */ case HA_ERR_TABLE_NEEDS_UPGRADE: + if (open_options & HA_OPEN_FOR_REPAIR) + { + rc= 0; + break; + } free_share(); /* fall through */ default: @@ -535,13 +554,6 @@ int ha_archive::open(const char *name, int mode, uint open_options) thr_lock_data_init(&share->lock, &lock, NULL); - DBUG_PRINT("ha_archive", ("archive table was crashed %s", - rc == HA_ERR_CRASHED_ON_USAGE ? "yes" : "no")); - if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR) - { - DBUG_RETURN(0); - } - DBUG_RETURN(rc); } @@ -1267,6 +1279,14 @@ int ha_archive::rnd_pos(uchar * buf, uchar *pos) DBUG_RETURN(get_row(&archive, buf)); } +int ha_archive::check_for_upgrade(HA_CHECK_OPT *check_opt) +{ + if (share->version < ARCHIVE_VERSION) + return HA_ADMIN_NEEDS_ALTER; + return 0; +} + + /* This method repairs the meta file. It does this by walking the datafile and rewriting the meta file. If EXTENDED repair is requested, we attempt to diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index ab630ed22fd..653a13b242d 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -35,7 +35,7 @@ typedef struct st_archive_record_buffer { typedef struct st_archive_share { char *table_name; char data_file_name[FN_REFLEN]; - uint table_name_length,use_count; + uint table_name_length,use_count, version; pthread_mutex_t mutex; THR_LOCK lock; azio_stream archive_write; /* Archive file we are working with */ @@ -133,6 +133,7 @@ public: int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); int optimize(THD* thd, HA_CHECK_OPT* check_opt); int repair(THD* thd, HA_CHECK_OPT* check_opt); + int check_for_upgrade(HA_CHECK_OPT *check_opt); void start_bulk_insert(ha_rows rows); int end_bulk_insert(); enum row_type get_row_type() const -- cgit v1.2.1