1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-33449 improving repair of tables

This task is to ensure we have a clear definition and rules of how to
repair or optimize a table.

The rules are:

- REPAIR should be used with tables that are crashed and are
  unreadable (hardware issues with not readable blocks, blocks with
  'unexpected data' etc)
- OPTIMIZE table should be used to optimize the storage layout for the
  table (recover space for delete rows and optimize the index
  structure.
- ALTER TABLE table_name FORCE should be used to rebuild the .frm file
  (the table definition) and the table (with the original table row
  format). If the table is from and older MariaDB/MySQL release with a
  different storage format, it will convert the data to the new
  format. ALTER TABLE ... FORCE is used as part of mariadb-upgrade

Here follows some more background:

The 3 ways to repair a table are:
1) ALTER TABLE table_name FORCE" (not other options).
   As an alias we allow: "ALTER TABLE table_name ENGINE=original_engine"
2) "REPAIR TABLE" (without FORCE)
3) "OPTIMIZE TABLE"

All of the above commands will optimize row space usage (which means that
space will be needed to hold a temporary copy of the table) and
re-generate all indexes. They will also try to replicate the original
table definition as exact as possible.

For ALTER TABLE and "REPAIR TABLE without FORCE", the following will hold:
If the table is from an older MariaDB version and data conversion is
needed (for example for old type HASH columns, MySQL JSON type or new
TIMESTAMP format) "ALTER TABLE table_name FORCE, algorithm=COPY" will be
used.

The differences between the algorithms are
1) Will use the fastest algorithm the engine supports to do a full repair
   of the table (except if data conversions are is needed).
2) Will use the storage engine internal REPAIR facility (MyISAM, Aria).
   If the engine does not support REPAIR then
   "ALTER TABLE FORCE, ALGORITHM=COPY" will be used.
   If there was data incompatibilities (which means that FORCE was used)
   then there will be a warning after REPAIR that ALTER TABLE FORCE is
   still needed.
   The reason for this is that REPAIR may be able to go around data
   errors (wrong incompatible data, crashed or unreadable sectors) that
   ALTER TABLE cannot do.
3) Will use the storage engine internal OPTIMIZE. If engine does not
   support optimize, then "ALTER TABLE FORCE" is used.

The above will ensure that ALTER TABLE FORCE is able to
correct almost any errors in the row or index data.  In case of
corrupted blocks then REPAIR possible followed by ALTER TABLE is needed.
This is important as mariadb-upgrade executes ALTER TABLE table_name
FORCE for any table that must be re-created.

Bugs fixed with InnoDB tables when using ALTER TABLE FORCE:
- No error for INNODB_DEFAULT_ROW_FORMAT=COMPACT even if row length
  would be too wide. (Independent of innodb_strict_mode).
- Tables using symlinks will be symlinked after any of the above commands
  (Independent of the setting of --symbolic-links)

If one specifies an algorithm together with ALTER TABLE FORCE, things
will work as before (except if data conversion is required as then
the COPY algorithm is enforced).

ALTER TABLE .. OPTIMIZE ALL PARTITIONS will work as before.

Other things:
- FORCE argument added to REPAIR to allow one to first run internal
  repair to fix damaged blocks and then follow it with ALTER TABLE.
- REPAIR will not update frm_version if ha_check_for_upgrade() finds
  that table is still incompatible with current version. In this case the
  REPAIR will end with an error.
- REPAIR for storage engines that does not have native repair, like InnoDB,
  is now using ALTER TABLE FORCE.
- REPAIR csv-table USE_FRM now works.
  - It did not work before as CSV tables had extension list in wrong
    order.
- Default error messages length for %M increased from 128 to 256 to not
  cut information from REPAIR.
- Documented HA_ADMIN_XX variables related to repair.
- Added HA_ADMIN_NEEDS_DATA_CONVERSION to signal that we have to
  do data conversions when converting the table (and thus ALTER TABLE
  copy algorithm is needed).
- Fixed typo in error message (caused test changes).
This commit is contained in:
Monty
2024-01-29 11:52:44 +02:00
committed by Sergei Golubchik
parent 2464ee758a
commit c4cad8d50c
41 changed files with 410 additions and 193 deletions

View File

@@ -101,7 +101,7 @@ static const char *handler_error_messages[]=
"Operation was interrupted by end user (probably kill command?)",
"Disk full",
/* 190 */
"Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry or dump and restore the table to fix this",
"Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this",
"Too many words in a FTS phrase or proximity search",
"Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.",
"Foreign key cascade delete/update exceeds max depth",

View File

@@ -44,7 +44,7 @@ C_MODE_START
area, and we would like to avoid unexpected truncation.
*/
#define MYSYS_ERRMSG_SIZE (512)
#define MYSYS_STRERROR_SIZE (128)
#define MYSYS_STRERROR_SIZE (256)
#define MY_FILE_ERROR ((size_t) -1)

View File

@@ -30,6 +30,7 @@
#define TT_USEFRM 1U
#define TT_FOR_UPGRADE 2U
#define TT_FROM_MYSQL 4U
#define TT_FORCE 8U
/* Bits set in out_flag */
#define O_NEW_DATA 2U

View File

@@ -27,7 +27,7 @@ rename table t2_innodb to t1_innodb;
truncate table t1_innodb;
repair table t1_innodb;
Table Op Msg_type Msg_text
test.t1_innodb repair note The storage engine for the table doesn't support repair
test.t1_innodb repair status OK
optimize table t1_innodb;
Table Op Msg_type Msg_text
test.t1_innodb optimize note Table does not support optimize, doing recreate + analyze instead
@@ -171,67 +171,68 @@ ALTER,InnoDB,0,test,t1_innodb,id: 3,InnoDB,0,test,t1_innodb,id: 4
RENAME,InnoDB,0,test,t1_innodb,id: 4,InnoDB,0,test,t2_innodb,id: 4
RENAME,InnoDB,0,test,t2_innodb,id: 4,InnoDB,0,test,t1_innodb,id: 4
TRUNCATE,InnoDB,0,test,t1_innodb,id: 4,,0,,,
repair,InnoDB,0,test,t1_innodb,id: 4,,0,,,
ALTER,InnoDB,0,test,t1_innodb,id: 4,InnoDB,0,test,t1_innodb,id: 5
DROP,InnoDB,0,test,t1_innodb,id: 5,,0,,,
CREATE,MyISAM,0,test,t20,id: 6,,0,,,
DROP,MyISAM,0,test,t20,id: 6,,0,,,
CREATE,MyISAM,0,test,t21,id: 7,,0,,,
DROP,MyISAM,0,test,t21,id: 7,,0,,,
CREATE,MyISAM,0,test,t30,id: 8,,0,,,
CREATE,MyISAM,0,test,t31,id: 9,,0,,,
DROP,MyISAM,0,test,t31,id: 9,,0,,,
repair,InnoDB,0,test,t1_innodb,id: 4,,0,,,
ALTER,InnoDB,0,test,t1_innodb,id: 5,InnoDB,0,test,t1_innodb,id: 6
DROP,InnoDB,0,test,t1_innodb,id: 6,,0,,,
CREATE,MyISAM,0,test,t20,id: 7,,0,,,
DROP,MyISAM,0,test,t20,id: 7,,0,,,
CREATE,MyISAM,0,test,t21,id: 8,,0,,,
DROP,MyISAM,0,test,t21,id: 8,,0,,,
CREATE,MyISAM,0,test,t30,id: 9,,0,,,
CREATE,MyISAM,0,test,t31,id: 10,,0,,,
DROP,MyISAM,0,test,t31,id: 10,,0,,,
DROP_AFTER_CREATE,MyISAM,0,test,t31,id: 11,,0,,,
CREATE,MyISAM,0,test,t32,id: 12,,0,,,
DROP,MyISAM,0,test,t30,id: 8,,0,,,
DROP,MyISAM,0,test,t32,id: 12,,0,,,
CREATE,MyISAM,0,test,t40,id: 13,,0,,,
CREATE,InnoDB,0,test,t41,id: 14,,0,,,
CREATE,MyISAM,0,test,t42,id: 15,,0,,,
DROP,MyISAM,0,test,t42,id: 15,,0,,,
CREATE,InnoDB,0,test,t42,id: 16,,0,,,
DROP,MyISAM,0,test,t40,id: 13,,0,,,
DROP,InnoDB,0,test,t41,id: 14,,0,,,
DROP,InnoDB,0,test,t42,id: 16,,0,,,
CREATE,MyISAM,0,test,t50,id: 17,,0,,,
CREATE,MyISAM,0,test,t51,id: 18,,0,,,
RENAME,MyISAM,0,test,t50,id: 17,MyISAM,0,test,t52,id: 17
RENAME,MyISAM,0,test,t51,id: 18,MyISAM,0,test,t53,id: 18
RENAME,MyISAM,0,test,t52,id: 17,MyISAM,0,test,tmp,id: 17
RENAME,MyISAM,0,test,t53,id: 18,MyISAM,0,test,t52,id: 18
RENAME,MyISAM,0,test,tmp,id: 17,MyISAM,0,test,t53,id: 17
DROP,MyISAM,0,test,t52,id: 18,,0,,,
DROP,MyISAM,0,test,t53,id: 17,,0,,,
CREATE,Aria,0,test,t60,id: 19,,0,,,
CHANGE_INDEX,Aria,0,test,t60,id: 19,,0,,,
CHANGE_INDEX,Aria,0,test,t60,id: 19,,0,,,
DROP,Aria,0,test,t60,id: 19,,0,,,
CREATE,Aria,0,test,t70,id: 20,,0,,,
BULK_INSERT,Aria,0,test,t70,id: 20,,0,,,
BULK_INSERT,Aria,0,test,t70,id: 20,,0,,,
CREATE,Aria,0,test,t71,id: 21,,0,,,
BULK_INSERT,Aria,0,test,t71,id: 21,,0,,,
DROP,Aria,0,test,t70,id: 20,,0,,,
DROP,Aria,0,test,t71,id: 21,,0,,,
CREATE,MyISAM,0,test,t@00201,id: 22,,0,,,
DROP,MyISAM,0,test,t@00201,id: 22,,0,,,
CREATE,MyISAM,0,test,t80,id: 23,,0,,,
CREATE,MyISAM,0,test,t31,id: 11,,0,,,
DROP,MyISAM,0,test,t31,id: 11,,0,,,
DROP_AFTER_CREATE,MyISAM,0,test,t31,id: 12,,0,,,
CREATE,MyISAM,0,test,t32,id: 13,,0,,,
DROP,MyISAM,0,test,t30,id: 9,,0,,,
DROP,MyISAM,0,test,t32,id: 13,,0,,,
CREATE,MyISAM,0,test,t40,id: 14,,0,,,
CREATE,InnoDB,0,test,t41,id: 15,,0,,,
CREATE,MyISAM,0,test,t42,id: 16,,0,,,
DROP,MyISAM,0,test,t42,id: 16,,0,,,
CREATE,InnoDB,0,test,t42,id: 17,,0,,,
DROP,MyISAM,0,test,t40,id: 14,,0,,,
DROP,InnoDB,0,test,t41,id: 15,,0,,,
DROP,InnoDB,0,test,t42,id: 17,,0,,,
CREATE,MyISAM,0,test,t50,id: 18,,0,,,
CREATE,MyISAM,0,test,t51,id: 19,,0,,,
RENAME,MyISAM,0,test,t50,id: 18,MyISAM,0,test,t52,id: 18
RENAME,MyISAM,0,test,t51,id: 19,MyISAM,0,test,t53,id: 19
RENAME,MyISAM,0,test,t52,id: 18,MyISAM,0,test,tmp,id: 18
RENAME,MyISAM,0,test,t53,id: 19,MyISAM,0,test,t52,id: 19
RENAME,MyISAM,0,test,tmp,id: 18,MyISAM,0,test,t53,id: 18
DROP,MyISAM,0,test,t52,id: 19,,0,,,
DROP,MyISAM,0,test,t53,id: 18,,0,,,
CREATE,Aria,0,test,t60,id: 20,,0,,,
CHANGE_INDEX,Aria,0,test,t60,id: 20,,0,,,
CHANGE_INDEX,Aria,0,test,t60,id: 20,,0,,,
DROP,Aria,0,test,t60,id: 20,,0,,,
CREATE,Aria,0,test,t70,id: 21,,0,,,
BULK_INSERT,Aria,0,test,t70,id: 21,,0,,,
BULK_INSERT,Aria,0,test,t70,id: 21,,0,,,
CREATE,Aria,0,test,t71,id: 22,,0,,,
BULK_INSERT,Aria,0,test,t71,id: 22,,0,,,
DROP,Aria,0,test,t70,id: 21,,0,,,
DROP,Aria,0,test,t71,id: 22,,0,,,
CREATE,MyISAM,0,test,t@00201,id: 23,,0,,,
DROP,MyISAM,0,test,t@00201,id: 23,,0,,,
CREATE,MyISAM,0,test,t80,id: 24,,0,,,
CREATE,VIEW,0,test,v1,,,0,,,
CREATE,TRIGGER,0,test,trg,,,0,,,
DROP,TRIGGER,0,test,trg,,,0,,,
DROP,VIEW,0,test,v1,,,0,,,
DROP,MyISAM,0,test,t80,id: 23,,0,,,
CREATE,MyISAM,0,test,t85,id: 24,,0,,,
ALTER,MyISAM,0,test,t85,id: 24,InnoDB,0,test,t85,id: 25
DROP,InnoDB,0,test,t85,id: 25,,0,,,
DROP,MyISAM,0,test,t80,id: 24,,0,,,
CREATE,MyISAM,0,test,t85,id: 25,,0,,,
ALTER,MyISAM,0,test,t85,id: 25,InnoDB,0,test,t85,id: 26
DROP,InnoDB,0,test,t85,id: 26,,0,,,
CREATE,DATABASE,0,mysqltest,,,,0,,,
CREATE,MyISAM,0,mysqltest,t90,id: 26,,0,,,
CREATE,InnoDB,0,mysqltest,t91,id: 27,,0,,,
CREATE,MyISAM,0,mysqltest,t90,id: 27,,0,,,
CREATE,InnoDB,0,mysqltest,t91,id: 28,,0,,,
ALTER,DATABASE,0,mysqltest,,,,0,,,
DROP,MyISAM,0,mysqltest,t90,id: 26,,0,,,
DROP,InnoDB,0,mysqltest,t91,id: 27,,0,,,
DROP,MyISAM,0,mysqltest,t90,id: 27,,0,,,
DROP,InnoDB,0,mysqltest,t91,id: 28,,0,,,
DROP,DATABASE,0,mysqltest,,,,0,,,
#
# Cleanup

View File

@@ -10,24 +10,39 @@ SELECT @@character_set_database;
latin1
SET @@character_set_database="latin1";
SELECT COUNT(*) FROM t1;
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
ALTER TABLE t1 FORCE;
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
test.t1 check Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
test.t1 check error Corrupt
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
test.t1 repair Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
test.t1 repair error Corrupt
REPAIR TABLE t1 FORCE;
Table Op Msg_type Msg_text
test.t1 repair Warning Can't open table
test.t1 repair error Corrupt
REPAIR TABLE t1 USE_FRM;
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t1 repair note Table data recovered
t1 repair error Table rebuild required. Please do "ALTER TABLE `test.t1` FORCE" or dump/reload to fix it!
test.t1 repair status Operation failed
SELECT COUNT(*) FROM t1;
COUNT(*)
0
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT COUNT(*) FROM t1;
COUNT(*)
0
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -64,15 +79,21 @@ SELECT @@character_set_database, 'taken from db.opt' AS comment;
@@character_set_database comment
latin1 taken from db.opt
SELECT COUNT(*) FROM t1;
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
REPAIR TABLE t1 USE_FRM;
Table Op Msg_type Msg_text
db1.t1 repair status OK
db1.t1 repair note Table data recovered
t1 repair error Table rebuild required. Please do "ALTER TABLE `db1.t1` FORCE" or dump/reload to fix it!
db1.t1 repair status Operation failed
SELECT COUNT(*) FROM t1;
COUNT(*)
0
CHECK TABLE t1;
Table Op Msg_type Msg_text
db1.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
Table Op Msg_type Msg_text
db1.t1 check status OK
SHOW CREATE TABLE t1;
Table Create Table

View File

@@ -18,11 +18,17 @@ SET @@character_set_database="latin1";
--error ER_GET_ERRNO
SELECT COUNT(*) FROM t1;
--error ER_GET_ERRNO
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
REPAIR TABLE t1;
REPAIR TABLE t1 FORCE;
REPAIR TABLE t1 USE_FRM;
SELECT COUNT(*) FROM t1;
CHECK TABLE t1;
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
SELECT COUNT(*) FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
SET @@character_set_database=DEFAULT;
@@ -50,6 +56,8 @@ SELECT COUNT(*) FROM t1;
REPAIR TABLE t1 USE_FRM;
SELECT COUNT(*) FROM t1;
CHECK TABLE t1;
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;

View File

@@ -125,12 +125,14 @@ id
# Run CHECK TABLE, it should indicate table need a REPAIR TABLE
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
# REPAIR old table USE_FRM should fail
REPAIR TABLE t1 USE_FRM;
Table Op Msg_type Msg_text
test.t1 repair warning Number of rows changed from 0 to 1
test.t1 repair status OK
test.t1 repair note Table data recovered
t1 repair error Table rebuild required. Please do "ALTER TABLE `test.t1` FORCE" or dump/reload to fix it!
test.t1 repair status Operation failed
# Run REPAIR TABLE to upgrade .frm file
REPAIR TABLE t1;
Table Op Msg_type Msg_text
@@ -190,23 +192,29 @@ drop tables t1, t2;
SET @save_global_character_set_server= @@global.character_set_server;
set @@global.character_set_server=@@character_set_server;
select count(*) from t1;
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
check table t1;
Table Op Msg_type Msg_text
test.t1 check Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
test.t1 check Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
test.t1 check error Corrupt
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You may have retry " from storage engine MyISAM
test.t1 repair Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You can try REPAIR TABLE ... USE_FRM possibly followed by ALTER TABLE ... FORCE or dump and restore the table to fix this" from storage engine MyISAM
test.t1 repair error Corrupt
repair table t1 use_frm;
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t1 repair note Table data recovered
t1 repair error Table rebuild required. Please do "ALTER TABLE `test.t1` FORCE" or dump/reload to fix it!
test.t1 repair status Operation failed
select count(*) from t1;
count(*)
0
check table t1;
Table Op Msg_type Msg_text
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
alter table t1 force;
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
set @@global.character_set_server=@save_global_character_set_server;
@@ -288,4 +296,17 @@ Warning 4200 The variable '@@alter_algorithm' is deleted and ignored. It it only
select @@alter_algorithm;
@@alter_algorithm
DEFAULT
#
# MDEV-33826 Assertion `tl->table == __null' failed in
# THD::open_temporary_table
#
CREATE TABLE t1 (i INT) ENGINE=InnoDB;
CREATE TABLE t2 (i INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE t3 (i INT);
REPAIR TABLE t1,t2,t3;
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair status OK
DROP TABLE t1,t2,t3;
# End of 11.5 tests

View File

@@ -4,6 +4,7 @@
--source include/have_sequence.inc
--source include/default_charset.inc
--source include/have_innodb.inc
call mtr.add_suppression("character set is multi-byte");
call mtr.add_suppression("exists only for compatibility");
@@ -219,6 +220,8 @@ repair table t1;
repair table t1 use_frm;
select count(*) from t1;
check table t1;
alter table t1 force;
check table t1;
drop table t1;
set @@global.character_set_server=@save_global_character_set_server;
@@ -287,4 +290,15 @@ set statement alter_algorithm=COPY FOR SELECT @@alter_algorithm;
select @@alter_algorithm;
--echo #
--echo # MDEV-33826 Assertion `tl->table == __null' failed in
--echo # THD::open_temporary_table
--echo #
CREATE TABLE t1 (i INT) ENGINE=InnoDB;
CREATE TABLE t2 (i INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE t3 (i INT);
REPAIR TABLE t1,t2,t3;
DROP TABLE t1,t2,t3;
--echo # End of 11.5 tests

View File

@@ -1350,7 +1350,7 @@ a
123.47
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
CALL show_table;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -1364,7 +1364,7 @@ a
123.47
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
CALL show_table;
Table Create Table
t1 CREATE TABLE `t1` (

View File

@@ -137,7 +137,7 @@ VERSION
a b
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
CALL show_table;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -149,7 +149,7 @@ VERSION
a b
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
CALL show_table;
Table Create Table
t1 CREATE TABLE `t1` (

View File

@@ -67,10 +67,18 @@ drop table `txu@0023p@0023p1`;
# check the table created using mysql 4.0
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
# query the table created using mysql 4.0
SELECT * FROM t1;
c1 c2 c3
ALTER TABLE t1 algorithm=NOCOPY;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
truncate t1;
drop table t1;

View File

@@ -61,6 +61,10 @@ copy_file std_data/bug37631.MYI $MYSQLD_DATADIR/test/t1.MYI;
CHECK TABLE t1;
--echo # query the table created using mysql 4.0
SELECT * FROM t1;
ALTER TABLE t1 algorithm=NOCOPY;
CHECK TABLE t1;
ALTER TABLE t1 FORCE;
CHECK TABLE t1;
DROP TABLE t1;
#

View File

@@ -5002,12 +5002,24 @@ connection default;
disconnect con1;
disconnect con2;
CREATE TABLE test_repair_table ( val integer not null ) ENGINE = CSV;
INSERT into test_repair_table values (1),(2);
CHECK TABLE test_repair_table;
Table Op Msg_type Msg_text
test.test_repair_table check status OK
REPAIR TABLE test_repair_table;
Table Op Msg_type Msg_text
test.test_repair_table repair status OK
SELECT * from test_repair_table;
val
1
2
REPAIR TABLE test_repair_table USE_FRM;
Table Op Msg_type Msg_text
test.test_repair_table repair status OK
SELECT * from test_repair_table;
val
1
2
DROP TABLE test_repair_table;
CREATE TABLE test_repair_table2 ( val integer not null ) ENGINE = CSV;
SELECT * from test_repair_table2;

View File

@@ -1402,9 +1402,13 @@ connection default;
CREATE TABLE test_repair_table ( val integer not null ) ENGINE = CSV;
INSERT into test_repair_table values (1),(2);
CHECK TABLE test_repair_table;
REPAIR TABLE test_repair_table;
SELECT * from test_repair_table;
REPAIR TABLE test_repair_table USE_FRM;
SELECT * from test_repair_table;
DROP TABLE test_repair_table;
#

View File

@@ -99,7 +99,7 @@ pk
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
REPAIR TABLE child;;
Table Op Msg_type Msg_text
test.child repair note The storage engine for the table doesn't support repair
test.child repair status OK
connection node_1;
COMMIT;
DROP TABLE child, parent;
@@ -119,7 +119,7 @@ pk
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
REPAIR TABLE child;;
Table Op Msg_type Msg_text
test.child repair note The storage engine for the table doesn't support repair
test.child repair status OK
connection node_1;
COMMIT;
DROP TABLE child, parent;
@@ -139,7 +139,7 @@ pk
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
REPAIR TABLE child;;
Table Op Msg_type Msg_text
test.child repair note The storage engine for the table doesn't support repair
test.child repair status OK
connection node_1;
COMMIT;
DROP TABLE child, parent;
@@ -159,7 +159,7 @@ pk
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
REPAIR TABLE child;;
Table Op Msg_type Msg_text
test.child repair note The storage engine for the table doesn't support repair
test.child repair status OK
connection node_1;
COMMIT;
DROP TABLE child, parent;

View File

@@ -3,7 +3,7 @@ connection node_1;
CREATE TABLE t1(a int not null primary key) engine=innodb;
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
CREATE VIEW v1 AS SELECT a FROM t1;
REPAIR VIEW v1;
Table Op Msg_type Msg_text

View File

@@ -27,7 +27,7 @@ test.t2 optimize note Table does not support optimize, doing recreate + analyze
test.t2 optimize status OK
connection node_2b;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t2 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
test.t2 repair status OK
DROP TABLE t1;
DROP TABLE t2;

View File

@@ -826,7 +826,7 @@ ERROR 42S02: Unknown table 't1' in HANDLER
handler t1 open;
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
handler t1 read next;
ERROR 42S02: Unknown table 't1' in HANDLER
#
@@ -950,7 +950,7 @@ handler t1 open;
lock tables t1 write;
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
unlock tables;
handler t1 read next;
ERROR 42S02: Unknown table 't1' in HANDLER

View File

@@ -830,7 +830,7 @@ ERROR 42S02: Unknown table 't1' in HANDLER
handler t1 open;
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
handler t1 read next;
ERROR 42S02: Unknown table 't1' in HANDLER
#
@@ -955,7 +955,7 @@ handler t1 open;
lock tables t1 write;
repair table t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
unlock tables;
handler t1 read next;
ERROR 42S02: Unknown table 't1' in HANDLER

View File

@@ -193,9 +193,13 @@ test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check note Auto_increment checked and .frm file version updated
test.t5_7 check status OK
test.t5_7b check note Auto_increment checked and .frm file version updated
test.t5_7b check status OK
test.t10_1 check note Auto_increment checked and .frm file version updated
test.t10_1 check status OK
test.t10_1b check note Auto_increment checked and .frm file version updated
test.t10_1b check status OK
SELECT * FROM t1;
id

View File

@@ -24,18 +24,13 @@ TRUNCATE TABLE t1;
TRUNCATE TABLE t2;
# restart
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
Warnings:
Warning 1618 <DATA DIRECTORY> option ignored
ALTER TABLE t2 FORCE, ALGORITHM=COPY;
Warnings:
Warning 1618 <DATA DIRECTORY> option ignored
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
Warnings:
Warning 1618 <DATA DIRECTORY> option ignored
t1.ibd
t2.ibd
DROP TABLE t2;
RENAME TABLE t1 TO t2;
ALTER TABLE t2 ADD UNIQUE INDEX(b), RENAME TO t3;

View File

@@ -1823,7 +1823,7 @@ DELETE FROM t4 WHERE c1 = 33;
#
REPAIR TABLE t4;
Table Op Msg_type Msg_text
test.t4 repair note The storage engine for the table doesn't support repair
test.t4 repair status OK
REPAIR TABLE t2;
Table Op Msg_type Msg_text
test.t2 repair status OK
@@ -1836,7 +1836,7 @@ c1
LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE;
REPAIR TABLE t4;
Table Op Msg_type Msg_text
test.t4 repair note The storage engine for the table doesn't support repair
test.t4 repair status OK
REPAIR TABLE t2;
Table Op Msg_type Msg_text
test.t2 repair status OK
@@ -2396,7 +2396,7 @@ Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
REPAIR TABLE m1;
Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
test.m1 repair status OK
DROP TABLE m1, t1;
CREATE TEMPORARY TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
REPAIR TABLE m1 USE_FRM;
@@ -2409,7 +2409,7 @@ Table Op Msg_type Msg_text
m1 repair error Cannot repair temporary table from .frm file
REPAIR TABLE m1;
Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
test.m1 repair status OK
DROP TABLE m1, t1;
create temporary table t1_temp(i int);
create temporary table tm_temp_temp (i int) engine=merge union=(t1_temp) insert_method=last;
@@ -3855,7 +3855,7 @@ Table Op Msg_type Msg_text
test.m1 check status OK
repair table m1;
Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
test.m1 repair status OK
checksum table m1;
Table Checksum
test.m1 3459908756
@@ -3868,7 +3868,7 @@ Table Op Msg_type Msg_text
test.m1 check status OK
repair table m1;
Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
test.m1 repair status OK
checksum table m1;
Table Checksum
test.m1 3459908756
@@ -3881,7 +3881,7 @@ Table Op Msg_type Msg_text
test.m1 check status OK
repair table m1;
Table Op Msg_type Msg_text
test.m1 repair note The storage engine for the table doesn't support repair
test.m1 repair status OK
checksum table m1;
Table Checksum
test.m1 3459908756

View File

@@ -87238,7 +87238,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -87693,7 +87693,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -88156,7 +88156,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -88617,7 +88617,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -89076,7 +89076,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -89539,7 +89539,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -90002,7 +90002,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;
@@ -90461,7 +90461,7 @@ test.t1 optimize status OK
# check layout success: 1
REPAIR TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
# check layout success: 1
TRUNCATE t1;

View File

@@ -574,7 +574,7 @@ test_rpl.t1 optimize status OK
******************** REPAIR TABLE ********************
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test_rpl.t1 repair note The storage engine for the table doesn't support repair
test_rpl.t1 repair status OK
******************** SET VARIABLE ********************
SET @test_rpl_var = 1;

View File

@@ -30,7 +30,7 @@ test.t1 optimize note Table does not support optimize, doing recreate + analyze
test.t1 optimize status OK
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected

View File

@@ -18,7 +18,7 @@ next value for s1
flush tables;
repair table s1;
Table Op Msg_type Msg_text
test.s1 repair note The storage engine for the table doesn't support repair
test.s1 repair status OK
select next value for s1;
next value for s1
2001
@@ -29,7 +29,7 @@ next value for s1
1
repair table s1;
Table Op Msg_type Msg_text
test.s1 repair note The storage engine for the table doesn't support repair
test.s1 repair status OK
check table s1;
Table Op Msg_type Msg_text
test.s1 check note The storage engine for the table doesn't support check

View File

@@ -92,7 +92,7 @@ a b
16301234-5566-f777-e888-99aabbccddee 63
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
CALL show_table(0);
Table Create Table
t1 CREATE TABLE `t1` (
@@ -110,7 +110,7 @@ a b
14701234-5566-b777-e888-99aabbccddee 47
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check error Upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it!
test.t1 check error Table rebuild required. Please do "ALTER TABLE `t1` FORCE" or dump/reload to fix it!
CALL show_table(0);
Table Create Table
t1 CREATE TABLE `t1` (

View File

@@ -4919,7 +4919,7 @@ bool handler::get_error_message(int error, String* buf)
Check for incompatible collation changes.
@retval
HA_ADMIN_NEEDS_UPGRADE Table may have data requiring upgrade.
HA_ADMIN_NEEDS_UPGRADE Table may have data requiring a recreate index
@retval
0 No upgrade required.
*/
@@ -4965,16 +4965,12 @@ int handler::check_long_hash_compatibility() const
/*
The old (pre-MDEV-27653) hash function was wrong.
So the long hash unique constraint can have some
duplicate records. REPAIR TABLE can't fix this,
it will fail on a duplicate key error.
Only "ALTER IGNORE TABLE .. FORCE" can fix this.
So we need to return HA_ADMIN_NEEDS_ALTER here,
(not HA_ADMIN_NEEDS_UPGRADE which is used elsewhere),
to properly send the error message text corresponding
to ER_TABLE_NEEDS_REBUILD (rather than to ER_TABLE_NEEDS_UPGRADE)
to the user.
duplicate records.
We use HA_ADMIN_NEEDS_DATA_CONVERSION to ensure that
key is re-generated and checked in ha_write_row().
This will send the error ER_TABLE_NEEDS_REBUILD to the user.
*/
return HA_ADMIN_NEEDS_ALTER;
return HA_ADMIN_NEEDS_DATA_CONVERSION;
}
}
return 0;
@@ -4989,7 +4985,7 @@ int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
if (table->s->incompatible_version ||
check_old_types())
return HA_ADMIN_NEEDS_ALTER;
return HA_ADMIN_NEEDS_DATA_CONVERSION;
if (!table->s->mysql_version)
{
@@ -5021,7 +5017,7 @@ int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
call above did not find data types that want upgrade.
*/
if (table->s->frm_version < FRM_VER_TRUE_VARCHAR)
return HA_ADMIN_NEEDS_ALTER;
return HA_ADMIN_NEEDS_DATA_CONVERSION;
if (unlikely((error= check_collation_compatibility())))
return error;
@@ -5232,6 +5228,11 @@ bool non_existing_table_error(int error)
HA_ADMIN_NEEDS_UPGRADE Table has structures requiring upgrade
@retval
HA_ADMIN_NEEDS_ALTER Table has structures requiring ALTER TABLE
@retval
HA_ADMIN_NEEDS_DATA_CONVERSION
Table has structures requiring
ALTER TABLE FORCE, algortithm=COPY to
recreate data.
@retval
HA_ADMIN_NOT_IMPLEMENTED
*/
@@ -5307,7 +5308,12 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
DBUG_ASSERT(result == HA_ADMIN_NOT_IMPLEMENTED ||
ha_table_flags() & HA_CAN_REPAIR);
if (result == HA_ADMIN_OK && !opt_readonly)
/*
Update frm version if no errors and there are no version incompatibiltes
in the data (as these are not fixed by repair).
*/
if (result == HA_ADMIN_OK && !opt_readonly &&
table->file->ha_check_for_upgrade(check_opt) == HA_ADMIN_OK)
result= update_frm_version(table);
return result;
}

View File

@@ -72,10 +72,28 @@ class select_result;
#define HA_ADMIN_TRY_ALTER -7
#define HA_ADMIN_WRONG_CHECKSUM -8
#define HA_ADMIN_NOT_BASE_TABLE -9
/*
Table needs to be rebuilt with handler::repair.
For example to fix a changed index sort order.
Rows with duplicated unique key values should be deleted.
For engines that do not support REPAIR, ALTER TABLE FORCE
is used.
*/
#define HA_ADMIN_NEEDS_UPGRADE -10
/*
Needs rebuild with ALTER TABLE ... FORCE.
Will recreate the .frm file with a new version to remove old
incompatibilities.
*/
#define HA_ADMIN_NEEDS_ALTER -11
#define HA_ADMIN_NEEDS_CHECK -12
#define HA_ADMIN_COMMIT_ERROR -13
/*
Needs rebuild with ALTER TABLE ... FORCE, ALGORITHM=COPY
This will take care of data conversions like MySQL JSON format
and updating version tables timestamps.
*/
#define HA_ADMIN_NEEDS_DATA_CONVERSION -12
#define HA_ADMIN_NEEDS_CHECK -13
#define HA_ADMIN_COMMIT_ERROR -14
/**
Return values for check_if_supported_inplace_alter().
@@ -2252,6 +2270,12 @@ struct Table_scope_and_contents_source_pod_st // For trivial members
enum_stats_auto_recalc stats_auto_recalc;
bool varchar; ///< 1 if table has a VARCHAR
bool sequence; // If SEQUENCE=1 was used
/*
True if we are using OPTIMIZE TABLE, REPAIR TABLE or ALTER TABLE FORCE
in which case the 'new' table should have identical storage layout
as the original.
*/
bool recreate_identical_table;
List<Virtual_column_info> *check_constraint_list;
@@ -5316,7 +5340,7 @@ private:
virtual void release_auto_increment() { return; };
/** admin commands - called from mysql_admin_table */
virtual int check_for_upgrade(HA_CHECK_OPT *check_opt)
{ return 0; }
{ return HA_ADMIN_OK; }
virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
{ return HA_ADMIN_NOT_IMPLEMENTED; }

View File

@@ -48,9 +48,11 @@ const LEX_CSTRING msg_optimize= { STRING_WITH_LEN("optimize") };
/* Prepare, run and cleanup for mysql_recreate_table() */
static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list,
Recreate_info *recreate_info)
Recreate_info *recreate_info,
bool table_copy)
{
bool result_code;
TABLE_LIST *save_next_global;
DBUG_ENTER("admin_recreate_table");
trans_rollback_stmt(thd);
@@ -68,8 +70,13 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list,
DEBUG_SYNC(thd, "ha_admin_try_alter");
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
/* Ignore if there is more than one table in the list */
save_next_global= table_list->next_global;
table_list->next_global= 0;
result_code= (thd->open_temporary_tables(table_list) ||
mysql_recreate_table(thd, table_list, recreate_info, false));
mysql_recreate_table(thd, table_list, recreate_info,
table_copy));
table_list->next_global= save_next_global;
reenable_binlog(thd);
/*
mysql_recreate_table() can push OK or ERROR.
@@ -286,6 +293,11 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
goto end;
}
}
/*
We have now fixed the table. However the frm file is still of old format.
We cannot update the frm_file to FRM_VER_TRUE_VARCHAR as the new format
are not compatible with the data.
*/
end:
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
@@ -532,7 +544,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
const LEX_CSTRING *operator_name,
thr_lock_type lock_type,
bool org_open_for_modify,
bool repair_table_use_frm,
bool no_errors_from_open,
uint extra_open_options,
int (*prepare_func)(THD *, TABLE_LIST *,
HA_CHECK_OPT *),
@@ -597,7 +609,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
uchar tabledef_version_buff[MY_UUID_SIZE];
const char *db= table->db.str;
bool fatal_error=0;
bool open_error= 0;
bool open_error= 0, recreate_used= 0;
bool require_data_conversion= 0, require_alter_table= 0;
bool collect_eis= FALSE;
bool open_for_modify= org_open_for_modify;
Recreate_info recreate_info;
@@ -635,7 +648,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
while (1)
{
open_error= open_only_one_table(thd, table,
repair_table_use_frm,
no_errors_from_open,
(view_operator_func != NULL));
thd->open_options&= ~extra_open_options;
@@ -859,28 +872,37 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/* purecov: end */
}
if (operator_func == &handler::ha_repair &&
!(check_opt->sql_flags & TT_USEFRM))
if (operator_func == &handler::ha_repair)
{
handler *file= table->table->file;
int check_for_upgrade= file->ha_check_for_upgrade(check_opt);
require_data_conversion=
check_for_upgrade == HA_ADMIN_NEEDS_DATA_CONVERSION;
require_alter_table= check_for_upgrade == HA_ADMIN_NEEDS_ALTER;
if (check_for_upgrade == HA_ADMIN_NEEDS_ALTER)
if (!(check_opt->sql_flags & (TT_USEFRM | TT_FORCE)))
{
/* 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, &recreate_info) ?
HA_ADMIN_FAILED : HA_ADMIN_OK;
thd->open_options&= ~extra_open_options;
goto send_result;
}
if (check_for_upgrade)
{
/* If repair is not implemented for the engine, run ALTER TABLE */
need_repair_or_alter= 1;
if (require_data_conversion || require_alter_table)
{
/* 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, &recreate_info, 1) ?
HA_ADMIN_FAILED : HA_ADMIN_OK);
recreate_used= 1;
thd->open_options&= ~extra_open_options;
goto send_result;
}
if (check_for_upgrade ||
!(table->table->file->ha_table_flags() & HA_CAN_REPAIR))
{
/*
If data upgrade is needed or repair is not implemented for the
engine, run ALTER TABLE FORCE
*/
need_repair_or_alter= 1;
}
}
}
result_code= compl_result_code= HA_ADMIN_OK;
if (operator_func == &handler::ha_analyze)
@@ -949,7 +971,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->lock_type= TL_READ;
DBUG_ASSERT(view_operator_func == NULL);
open_error= open_only_one_table(thd, table,
repair_table_use_frm, FALSE);
no_errors_from_open, FALSE);
thd->open_options&= ~extra_open_options;
if (unlikely(!open_error))
@@ -1092,10 +1114,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
repair was not implemented and we need to upgrade the table
to a new version so we recreate the table with ALTER TABLE
*/
result_code= admin_recreate_table(thd, table, &recreate_info);
result_code= admin_recreate_table(thd, table, &recreate_info, 1);
recreate_used= 1;
}
send_result:
send_result:
lex->cleanup_after_one_table_open();
thd->clear_error(); // these errors shouldn't get client
@@ -1136,6 +1159,34 @@ send_result:
}
thd->get_stmt_da()->clear_warning_info(thd->query_id);
}
/*
Give a warning if REPAIR TABLE was used but table still needs an
ALTER TABLE. This can only happen for old type tables where REPAIR
was using FORCE to recover old data.
*/
if (operator_func == &handler::ha_repair && ! recreate_used &&
(require_data_conversion || require_alter_table))
{
char buf[MYSQL_ERRMSG_SIZE];
if (result_code == HA_ADMIN_OK)
{
protocol->prepare_for_resend();
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(STRING_WITH_LEN("Table data recovered"),system_charset_info);
if (protocol->write())
goto err;
}
my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_TABLE_NEEDS_REBUILD),
table_name.str);
if (send_check_errmsg(thd, table, operator_name, buf) < 0)
goto err;
result_code= HA_ADMIN_FAILED;
}
protocol->prepare_for_resend();
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
@@ -1227,7 +1278,8 @@ send_result_message:
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
result_code= admin_recreate_table(thd, table, &recreate_info);
result_code= admin_recreate_table(thd, table, &recreate_info, 0);
recreate_used= 1;
trans_commit_stmt(thd);
trans_commit(thd);
close_thread_tables(thd);
@@ -1310,6 +1362,7 @@ send_result_message:
}
case HA_ADMIN_NEEDS_UPGRADE:
case HA_ADMIN_NEEDS_DATA_CONVERSION:
case HA_ADMIN_NEEDS_ALTER:
{
char buf[MYSQL_ERRMSG_SIZE];
@@ -1318,7 +1371,7 @@ send_result_message:
table->table->file->ha_table_flags() & HA_CAN_REPAIR ? "TABLE" : 0;
protocol->store(&error_clex_str, system_charset_info);
if (what_to_upgrade)
if (what_to_upgrade && result_code == HA_ADMIN_NEEDS_UPGRADE)
length= my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_TABLE_NEEDS_UPGRADE),
what_to_upgrade, table->table_name.str);
@@ -1611,7 +1664,8 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table, &recreate_info, true) :
mysql_recreate_table(thd, first_table, &recreate_info,
false) :
mysql_admin_table(thd, first_table, &m_lex->check_opt,
&msg_optimize, TL_WRITE, 1, 0, 0, 0,
&handler::ha_optimize, 0, true);
@@ -1639,7 +1693,8 @@ bool Sql_cmd_repair_table::execute(THD *thd)
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, &msg_repair,
TL_WRITE, 1,
MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM),
MY_TEST(m_lex->check_opt.sql_flags &
(TT_USEFRM | TT_FORCE)),
HA_OPEN_FOR_REPAIR, &prepare_for_repair,
&handler::ha_repair, &view_repair, true);

View File

@@ -319,7 +319,10 @@ public:
*/
enum_alter_table_algorithm algorithm(const THD *thd) const;
bool algorithm_is_nocopy(const THD *thd) const;
bool algorithm_not_specified() const
{
return requested_algorithm == ALTER_TABLE_ALGORITHM_NONE;
}
uint check_vcol_field(Item_field *f) const;
private:

View File

@@ -4938,9 +4938,6 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
!(thd->work_part_info= thd->work_part_info->get_clone(thd)))
DBUG_RETURN(TRUE);
/* ALTER_PARTITION_ADMIN is handled in mysql_admin_table */
DBUG_ASSERT(!(alter_info->partition_flags & ALTER_PARTITION_ADMIN));
partition_info *saved_part_info= NULL;
if (alter_info->partition_flags &

View File

@@ -10214,11 +10214,12 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
TABLE *table, *new_table= nullptr;
DDL_LOG_STATE ddl_log_state;
Turn_errors_to_warnings_handler errors_to_warnings;
HA_CHECK_OPT check_opt;
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool partition_changed= false;
bool fast_alter_partition= false;
#endif
bool require_copy_algorithm;
bool partial_alter= false;
/*
start_alter_id is the gtid seq no of the START Alter - the 1st part
@@ -10898,19 +10899,56 @@ do_continue:;
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
/*
ALTER TABLE ... ENGINE to the same engine is a common way to
request table rebuild. Set ALTER_RECREATE flag to force table
rebuild.
*/
if (new_db_type == old_db_type)
{
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
alter_info->flags|= ALTER_RECREATE;
/*
Check if we are using ALTER TABLE FORCE without any other options
(except ENGINE == current_engine).
In this case we will try to recreate an identical to the original.
This code is also used with REPAIR and OPTIMIZE.
*/
if (alter_info->flags == ALTER_RECREATE &&
((create_info->used_fields & ~HA_CREATE_USED_ENGINE) == 0))
create_info->recreate_identical_table= 1;
}
/*
We can use only copy algorithm if one of the following is true:
- If the table is from an old MariaDB version and requires data
modifications. In this case we ignore --alter-algorithm as
as we cannot use any other algorithm than COPY (using other
algorithms could open up the problem that the table .frm version
is updated without data transformations and the table would be
corrupted without any way for MariaDB to notice this during
check/upgrade).
This logic ensurses that ALTER TABLE ... FORCE (no other
options) will always be be able to repair a table structure and
convert data from any old format.
- In-place is impossible for given operation.
- Changes to partitioning which were not handled by fast_alter_part_table()
needs to be handled using table copying algorithm unless the engine
supports auto-partitioning as such engines can do some changes
using in-place API.
*/
if (is_inplace_alter_impossible(table, create_info, alter_info)
|| IF_PARTITIONING((partition_changed &&
!(old_db_type->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
check_opt.init();
require_copy_algorithm= (table->file->ha_check_for_upgrade(&check_opt) ==
HA_ADMIN_NEEDS_DATA_CONVERSION);
if (require_copy_algorithm ||
is_inplace_alter_impossible(table, create_info, alter_info) ||
IF_PARTITIONING((partition_changed &&
!(old_db_type->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
{
if (alter_info->algorithm_is_nocopy(thd))
if (alter_info->algorithm_is_nocopy(thd) &&
!(require_copy_algorithm && alter_info->algorithm_not_specified()))
{
my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
alter_info->algorithm_clause(thd), "ALGORITHM=COPY");
@@ -10920,15 +10958,6 @@ do_continue:;
alter_info->set_requested_algorithm(Alter_info::ALTER_TABLE_ALGORITHM_COPY);
}
/*
ALTER TABLE ... ENGINE to the same engine is a common way to
request table rebuild. Set ALTER_RECREATE flag to force table
rebuild.
*/
if (new_db_type == old_db_type &&
create_info->used_fields & HA_CREATE_USED_ENGINE)
alter_info->flags|= ALTER_RECREATE;
/*
Handling of symlinked tables:
If no rename:
@@ -12470,6 +12499,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
mysql_recreate_table()
thd Thread handler
table_list Table to recreate
partition_admin Optimizing partitions
table_copy Recreate the table by using
ALTER TABLE COPY algorithm
@@ -12478,7 +12508,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
*/
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
Recreate_info *recreate_info, bool table_copy)
Recreate_info *recreate_info,
bool table_copy)
{
Table_specification_st create_info;
Alter_info alter_info;
@@ -12495,12 +12526,13 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
create_info.init();
create_info.row_type=ROW_TYPE_NOT_USED;
create_info.alter_info= &alter_info;
create_info.recreate_identical_table= 1;
/* Force alter table to recreate table */
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
alter_info.partition_flags= thd->lex->alter_info.partition_flags;
if (table_copy)
alter_info.set_requested_algorithm(
Alter_info::ALTER_TABLE_ALGORITHM_COPY);
if (table_copy && !(alter_info.partition_flags & ALTER_PARTITION_ADMIN))
alter_info.set_requested_algorithm(Alter_info::ALTER_TABLE_ALGORITHM_COPY);
bool res= mysql_alter_table(thd, &null_clex_str, &null_clex_str, &create_info,
table_list, recreate_info, &alter_info, 0,
@@ -12829,7 +12861,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
/*
Since CREATE_INFO is not full without Alter_info, it is better to pass them
as a signle parameter. TODO: remove alter_info argument where create_info is
as a single parameter. TODO: remove alter_info argument where create_info is
passed.
*/
create_info.alter_info= &alter_info;

View File

@@ -165,7 +165,8 @@ bool mysql_compare_tables(TABLE *table,
HA_CREATE_INFO *create_info,
bool *metadata_equal);
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
class Recreate_info *recreate_info, bool table_copy);
class Recreate_info *recreate_info,
bool table_copy);
bool mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
const LEX_CSTRING *old_name, const LEX_CSTRING *new_db,
const LEX_CSTRING *new_name, const LEX_CUSTRING *id,

View File

@@ -2234,6 +2234,7 @@ int view_checksum(THD *thd, TABLE_LIST *view)
@retval HA_ADMIN_OK OK
@retval HA_ADMIN_NOT_IMPLEMENTED it is not VIEW
@retval HA_ADMIN_WRONG_CHECKSUM check sum is wrong
@retval HA_ADMIN_NEEDS_UPGRADE We need to recreate the view
*/
int view_check(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt)
{

View File

@@ -8223,6 +8223,7 @@ mi_repair_type:
QUICK { Lex->check_opt.flags|= T_QUICK; }
| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
| USE_FRM { Lex->check_opt.sql_flags|= TT_USEFRM; }
| FORCE_SYM { Lex->check_opt.sql_flags|= TT_FORCE; }
;
opt_view_repair_type:

View File

@@ -1858,6 +1858,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
share->frm_version= frm_image[2];
if (share->frm_version < FRM_VER_TRUE_VARCHAR)
share->keep_original_mysql_version= 1;
/*
Check if .frm file created by MySQL 5.0. In this case we want to
display CHAR fields as CHAR and not as VARCHAR.

View File

@@ -167,9 +167,9 @@ static void init_tina_psi_keys(void)
extensions exist for this handler.
*/
static const char *ha_tina_exts[] = {
CSN_EXT,
CSV_EXT,
CSM_EXT,
CSN_EXT,
NullS
};

View File

@@ -11194,7 +11194,7 @@ create_table_info_t::create_options_are_invalid()
if (!m_create_info->data_file_name
|| !m_create_info->data_file_name[0]) {
} else if (!my_use_symdir) {
} else if (!my_use_symdir && !m_create_info->recreate_identical_table) {
my_error(WARN_OPTION_IGNORED, MYF(ME_WARNING),
"DATA DIRECTORY");
} else if (!create_option_data_directory_is_valid()) {
@@ -11474,7 +11474,7 @@ create_table_info_t::parse_table_name(
we ignore the DATA DIRECTORY. */
if (m_create_info->data_file_name
&& m_create_info->data_file_name[0]
&& my_use_symdir) {
&& (my_use_symdir || m_create_info->recreate_identical_table)) {
if (!create_option_data_directory_is_valid()) {
push_warning_printf(
m_thd, Sql_condition::WARN_LEVEL_WARN,
@@ -11944,7 +11944,7 @@ create_table_info_t::set_tablespace_type(
m_use_file_per_table
&& m_create_info->data_file_name
&& m_create_info->data_file_name[0]
&& my_use_symdir;
&& (my_use_symdir || m_create_info->recreate_identical_table);
}
/** Initialize the create_table_info_t object.
@@ -12646,8 +12646,9 @@ create_table_info_t::create_foreign_keys()
}
/** Create the internal innodb table.
@param create_fk whether to add FOREIGN KEY constraints */
int create_table_info_t::create_table(bool create_fk)
@param create_fk whether to add FOREIGN KEY constraints
@param strict whether to give warnings for too big rows */
int create_table_info_t::create_table(bool create_fk, bool strict)
{
int error;
int primary_key_no;
@@ -12826,7 +12827,7 @@ int create_table_info_t::create_table(bool create_fk)
/* In TRUNCATE TABLE, we will merely warn about the maximum
row size being too large. */
if (!row_size_is_acceptable(*m_table, create_fk)) {
if (!row_size_is_acceptable(*m_table, create_fk && strict)) {
DBUG_RETURN(convert_error_code_to_mysql(
DB_TOO_BIG_RECORD, m_flags, NULL));
}
@@ -13171,7 +13172,7 @@ ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info,
/* We can't possibly have foreign key information when creating a
stub table for importing .frm / .cfg / .ibd because it is not
stored in any of these files. */
error= info.create_table(own_trx);
error= info.create_table(own_trx, !create_info->recreate_identical_table);
if (own_trx || (info.flags2() & DICT_TF2_TEMPORARY))
{

View File

@@ -640,7 +640,7 @@ public:
/** Create the internal innodb table.
@param create_fk whether to add FOREIGN KEY constraints */
int create_table(bool create_fk = true);
int create_table(bool create_fk = true, bool strict= true);
static void create_table_update_dict(dict_table_t* table, THD* thd,
const HA_CREATE_INFO& info,

View File

@@ -4,23 +4,23 @@ INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b');
CREATE TABLE t2 (a INT, b CHAR(8) PRIMARY KEY) ENGINE=rocksdb;
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
INSERT INTO t1 (a,b) VALUES (3,'c');
INSERT INTO t2 (a,b) VALUES (4,'d');
REPAIR NO_WRITE_TO_BINLOG TABLE t1, t2;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
test.t2 repair note The storage engine for the table doesn't support repair
test.t1 repair status OK
test.t2 repair status OK
INSERT INTO t2 (a,b) VALUES (5,'e'),(6,'f');
REPAIR LOCAL TABLE t2;
Table Op Msg_type Msg_text
test.t2 repair note The storage engine for the table doesn't support repair
test.t2 repair status OK
INSERT INTO t1 (a,b) VALUES (7,'g'),(8,'h');
INSERT INTO t2 (a,b) VALUES (9,'i');
REPAIR LOCAL TABLE t2, t1 EXTENDED;
Table Op Msg_type Msg_text
test.t2 repair note The storage engine for the table doesn't support repair
test.t1 repair note The storage engine for the table doesn't support repair
test.t2 repair status OK
test.t1 repair status OK
INSERT INTO t1 (a,b) VALUES (10,'j');
INSERT INTO t2 (a,b) VALUES (11,'k');
REPAIR TABLE t1, t2 QUICK USE_FRM;