Commit c8737515 authored by Anurag Shekhar's avatar Anurag Shekhar

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.
parent 313c5a01
...@@ -12717,3 +12717,14 @@ COUNT(t1.a) ...@@ -12717,3 +12717,14 @@ COUNT(t1.a)
729 729
DROP TABLE t1; DROP TABLE t1;
SET @@join_buffer_size= @save_join_buffer_size; 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;
...@@ -1623,3 +1623,24 @@ INSERT INTO t1 VALUES('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), ...@@ -1623,3 +1623,24 @@ INSERT INTO t1 VALUES('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
SELECT COUNT(t1.a) FROM t1, t1 a, t1 b, t1 c, t1 d, t1 e; SELECT COUNT(t1.a) FROM t1, t1 a, t1 b, t1 c, t1 d, t1 e;
DROP TABLE t1; DROP TABLE t1;
SET @@join_buffer_size= @save_join_buffer_size; SET @@join_buffer_size= @save_join_buffer_size;
#
# BUG#47012 archive tables are not upgradeable, and server crashes on any access
#
let $MYSQLD_DATADIR= `SELECT @@datadir`;
copy_file std_data/bug47012.frm $MYSQLD_DATADIR/test/t1.frm;
copy_file std_data/bug47012.ARZ $MYSQLD_DATADIR/test/t1.ARZ;
copy_file std_data/bug47012.ARM $MYSQLD_DATADIR/test/t1.ARM;
--error ER_TABLE_NEEDS_UPGRADE
SHOW CREATE TABLE t1;
--error ER_TABLE_NEEDS_UPGRADE
SELECT * FROM t1;
--error ER_TABLE_NEEDS_UPGRADE
INSERT INTO t1 (col1, col2) VALUES (1, "value");
REPAIR TABLE t1;
DROP TABLE t1;
remove_file $MYSQLD_DATADIR/test/t1.ARM;
...@@ -69,7 +69,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd) ...@@ -69,7 +69,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd)
s->transparent = 0; s->transparent = 0;
s->mode = 'r'; s->mode = 'r';
s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */ 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. We do our own version of append by nature.
...@@ -352,10 +352,19 @@ void read_header(azio_stream *s, unsigned char *buffer) ...@@ -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->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS);
s->dirty= (unsigned int)buffer[AZ_DIRTY_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;
} }
} }
......
...@@ -360,6 +360,12 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc) ...@@ -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; stats.auto_increment_value= archive_tmp.auto_increment + 1;
share->rows_recorded= (ha_rows)archive_tmp.rows; share->rows_recorded= (ha_rows)archive_tmp.rows;
share->crashed= archive_tmp.dirty; 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); azclose(&archive_tmp);
VOID(my_hash_insert(&archive_open_tables, (uchar*) share)); 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) ...@@ -491,7 +497,15 @@ int ha_archive::open(const char *name, int mode, uint open_options)
(open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no")); (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no"));
share= get_share(name, &rc); 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 */ /* purecov: begin inspected */
free_share(); free_share();
......
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