From 9f85560212241f07b7bdff7df639c0b9a519bed5 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 3 Sep 2010 20:55:56 +0300 Subject: [PATCH] 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 ...077376?cio_com.MYD => long_table_name.MYD} | Bin ...077376?cio_com.MYI => long_table_name.MYI} | Bin ...077376?cio_com.frm => long_table_name.frm} | Bin 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 +- 13 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 rename mysql-test/std_data/{ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD => long_table_name.MYD} (100%) rename mysql-test/std_data/{ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI => long_table_name.MYI} (100%) rename mysql-test/std_data/{ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm => long_table_name.frm} (100%) 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 0000000000000000000000000000000000000000..8f1111437d81045087daaefaa2d8dea0e7173954 GIT binary patch literal 19 McmeyzsKkH<02M(2A^-pY literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d24e76884cccf9df7d5c17e9733816fa17411b36 GIT binary patch literal 138 zcmb2|=3oE==HJIT7^2=i+`|Oq%ELu}eYP)5Vb)_~YqS49+0870g$*SC|Nq-dj)Dvd z3@i)R-L`MyKfakQ<-v@ECeD7&nFeYphh|LROmPpm>?L;ENbXELP$W65CndE62kNF7Q7ebO6agi!u~V8{-S9= z+k2Rzv_NTql`e4Fyi0OS02g<8%1Ui+cfhBhu7N6TxKe-u6rcbFC_n)UP=Epypa2CZ z@UsGf(BJLT_0bTUG1jNeZhzhm@$q~!1t>rP3Q&Lo6rcbFC_n)U{GY(p=%@dH%Rtbe z(5VM!M!mxkbIoHlup+Z%^<^Q0v^p~(9WptD*C7`@W~vhuPP~U0EMj0a2yN&Bo*PaT Avj6}9 literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD b/mysql-test/std_data/long_table_name.MYD similarity index 100% rename from mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYD rename to mysql-test/std_data/long_table_name.MYD diff --git a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI b/mysql-test/std_data/long_table_name.MYI similarity index 100% rename from mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.MYI rename to mysql-test/std_data/long_table_name.MYI diff --git a/mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm b/mysql-test/std_data/long_table_name.frm similarity index 100% rename from mysql-test/std_data/ltoriaeinnovacionendesarrolloempres?9120761097220077376?cio_com.frm rename to mysql-test/std_data/long_table_name.frm 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