From c87375150b922526f9699aee86614481ac711ad0 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Wed, 11 Nov 2009 13:33:29 +0530 Subject: [PATCH] Bug #47012 archive tables are not upgradeable, and server crashes on any access Archive engine for 5.1 (and latter) version uses a modified version of zlib (azlib). These two version are incompatible so a proper upgrade is needed before tables created in 5.0 can be used reliable. This upgrade can be performed using repair. But due to lack of test its risky to allow upgrade for now. This patch addresses only the crashing issue. Any attempt to repair will be blocked. Eventually repair can be allowed to run through (which will also cause an upgrade from older version to newer) but only after a thorough testing. mysql-test/r/archive.result: Updated result file for test case for bug#47012 mysql-test/std_data/bug47012.ARM: part of archive table (t1) created in mysql 5.0 mysql-test/std_data/bug47012.ARZ: part of archive table (t1) created in mysql 5.0 mysql-test/std_data/bug47012.frm: part of archive table (t1) created in mysql 5.0 mysql-test/t/archive.test: Added test case for bug#47012. storage/archive/azio.c: Fixed a minor issues (minor version overwriting version in stream structure) Removed assertion when an older version is found. Instead setting the correct version (2) in s->version If an unknown version is found marked it as corrupt. storage/archive/ha_archive.cc: Detecting the archive version in getShare and marking it as need to upgrade. Blocking open if the archive needs an upgrade. This can be allowed in case of open for repair to upgrade the archive but needs to tested. --- mysql-test/r/archive.result | 11 +++++++++++ mysql-test/std_data/bug47012.ARM | Bin 0 -> 19 bytes mysql-test/std_data/bug47012.ARZ | Bin 0 -> 22 bytes mysql-test/std_data/bug47012.frm | Bin 0 -> 8590 bytes mysql-test/t/archive.test | 21 +++++++++++++++++++++ storage/archive/azio.c | 17 +++++++++++++---- storage/archive/ha_archive.cc | 16 +++++++++++++++- 7 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 mysql-test/std_data/bug47012.ARM create mode 100644 mysql-test/std_data/bug47012.ARZ create mode 100644 mysql-test/std_data/bug47012.frm diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index e865d775c6a..c620eb97cab 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12717,3 +12717,14 @@ COUNT(t1.a) 729 DROP TABLE t1; SET @@join_buffer_size= @save_join_buffer_size; +SHOW CREATE TABLE t1; +ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +SELECT * FROM t1; +ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! +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 +DROP TABLE t1; diff --git a/mysql-test/std_data/bug47012.ARM b/mysql-test/std_data/bug47012.ARM new file mode 100644 index 0000000000000000000000000000000000000000..86bbaf829d22ee058861f931dae20197622b040c GIT binary patch literal 19 Lcmeyz$bb$268`}J literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/bug47012.ARZ b/mysql-test/std_data/bug47012.ARZ new file mode 100644 index 0000000000000000000000000000000000000000..f2aa19ffea67065ff063620cb31f822785e61579 GIT binary patch literal 22 Zcmb2|=3oE==HJIT7^2=i+`|Oq0suAJ1!n*N literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/bug47012.frm b/mysql-test/std_data/bug47012.frm new file mode 100644 index 0000000000000000000000000000000000000000..6c0a535cce7cd14adb9e554ed62e94177d2c109d GIT binary patch literal 8590 zcmeI&Jqp4=5QgC|8`r-GrU(|X(ALVI6DT5RCl+47R`3d*z;k#H?`51VvbL6r?-ZGt zkFbQN%|4TEo=SNl&8(?ZEZ0^?@?me+VQ$0yA!T(iol4_+p(B6*0tg_000IagfB*sr zAb`Nv3OH5q+ul=*;?UCSu-@*Do0u>lfB*srAbP3gW29}3fDs`@yj6Wtransparent = 0; s->mode = 'r'; s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */ - s->version = (unsigned char)az_magic[2]; /* minor version */ + s->minor_version= (unsigned char) az_magic[2]; /* minor version */ /* We do our own version of append by nature. @@ -352,10 +352,19 @@ void read_header(azio_stream *s, unsigned char *buffer) s->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS); s->dirty= (unsigned int)buffer[AZ_DIRTY_POS]; } - else + else if (buffer[0] == gz_magic[0] && buffer[1] == gz_magic[1]) { - DBUG_ASSERT(buffer[0] == az_magic[0] && buffer[1] == az_magic[1]); - return; + /* + Set version number to previous version (2). + */ + s->version= (unsigned char) 2; + } else { + /* + Unknown version. + Most probably due to a corrupt archive. + */ + s->dirty= AZ_STATE_DIRTY; + s->z_err= Z_VERSION_ERROR; } } diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 6fa8333c1b7..4648ca798da 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -360,6 +360,12 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc) stats.auto_increment_value= archive_tmp.auto_increment + 1; share->rows_recorded= (ha_rows)archive_tmp.rows; share->crashed= archive_tmp.dirty; + /* + If archive version is less than 3, It should be upgraded before + use. + */ + if (archive_tmp.version < ARCHIVE_VERSION) + *rc= HA_ERR_TABLE_NEEDS_UPGRADE; azclose(&archive_tmp); VOID(my_hash_insert(&archive_open_tables, (uchar*) share)); @@ -491,7 +497,15 @@ int ha_archive::open(const char *name, int mode, uint open_options) (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no")); share= get_share(name, &rc); - if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR)) + /* + Allow open on crashed table in repair mode only. + Block open on 5.0 ARCHIVE table. Though we have almost all + routines to access these tables, they were not well tested. + For now we have to refuse to open such table to avoid + potential data loss. + */ + if ((rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR)) + || rc == HA_ERR_TABLE_NEEDS_UPGRADE) { /* purecov: begin inspected */ free_share();