Information about table definitions is stored both in the
.frm files, and in the InnoDB
data dictionary. If
you move .frm files around, or if the server
crashes in the middle of a data dictionary operation, these
sources of information can become inconsistent.
If a data dictionary corruption or consistency issue prevents you
from starting InnoDB, see
Section 14.22.2, “Forcing InnoDB Recovery” for information about
manual recovery.
A symptom of an out-of-sync data dictionary is that a
CREATE TABLE statement fails. If
this occurs, look in the server's error log. If the log says
that the table already exists inside the
InnoDB internal data dictionary, you have an
orphan table inside the InnoDB tablespace
files that has no corresponding .frm file.
The error message looks like this:
InnoDB: Error: table test/parent already exists in InnoDB internal
InnoDB: data dictionary. Have you deleted the .frm file
InnoDB: and not used DROP TABLE? Have you used DROP DATABASE
InnoDB: for InnoDB tables in MySQL version <= 3.23.43?
InnoDB: See the Restrictions section of the InnoDB manual.
InnoDB: You can drop the orphaned table inside InnoDB by
InnoDB: creating an InnoDB table with the same name in another
InnoDB: database and moving the .frm file to the current database.
InnoDB: Then MySQL thinks the table exists, and DROP TABLE will
InnoDB: succeed.
You can drop the orphan table by following the instructions
given in the error message. If you are still unable to use
DROP TABLE successfully, the
problem may be due to name completion in the
mysql client. To work around this problem,
start the mysql client with the
--skip-auto-rehash
option and try DROP TABLE again.
(With name completion on, mysql tries to
construct a list of table names, which fails when a problem such
as just described exists.)
With innodb_file_per_table
enabled (the default), the following messages may appear at
startup if a
file-per-table
tablespace file (.ibd file) is missing:
[ERROR] InnoDB: Operating system error number 2 in a file operation.
[ERROR] InnoDB: The error means the system cannot find the path specified.
[ERROR] InnoDB: Cannot open datafile for read-only: './test/t1.ibd' OS error: 71
[Warning] InnoDB: Ignoring tablespace `test/t1` because it could not be opened.
To address these messages, issue DROP
TABLE statement to remove data about the missing table
from the data dictionary.
Another symptom of an out-of-sync data dictionary is that MySQL
prints an error that it cannot open an
InnoDB file:
ERROR 1016: Can't open file: 'child2.ibd'. (errno: 1)In the error log you can find a message like this:
InnoDB: Cannot find table test/child2 from the internal data dictionary
InnoDB: of InnoDB though the .frm file for the table exists. Maybe you
InnoDB: have deleted and recreated InnoDB data files but have forgotten
InnoDB: to delete the corresponding .frm files of InnoDB tables?
This means that there is an orphan .frm
file without a corresponding table inside
InnoDB. You can drop the orphan
.frm file by deleting it manually.
If MySQL exits in the middle of an in-place
ALTER TABLE operation
(ALGORITHM=INPLACE), you may be left with an
orphan intermediate table that takes up space on your system.
Also, an orphan intermediate table in an otherwise empty
general
tablespace prevents you from dropping the general
tablespace. This section describes how to identify and remove
orphan intermediate tables.
Intermediate table names begin with an
#sql-ib prefix (e.g.,
#sql-ib87-856498050). The accompanying
.frm file has an
#sql-* prefix and is named differently
(e.g., #sql-36ab_2.frm).
To identify orphan intermediate tables on your system, you can
query the Information Schema
INNODB_SYS_TABLES table. Look for
table names that begin with #sql. If the
original table resides in a
file-per-table
tablespace, the tablespace file (the
#sql-*.ibd file) for the orphan
intermediate table should be visible in the database directory.
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE '%#sql%';To remove an orphan intermediate table, perform the following steps:
In the database directory, rename the
#sql-*.frmfile to match the base name of the orphan intermediate table:$> mv #sql-36ab_2.frm #sql-ib87-856498050.frmNoteIf there is no
.frmfile, you can recreate it. The.frmfile must have the same table schema as the orphan intermediate table (it must have the same columns and indexes) and must be placed in the database directory of the orphan intermediate table.Drop the orphan intermediate table by issuing a
DROP TABLEstatement, prefixing the name of the table with#mysql50#and enclosing the table name in backticks. For example:mysql> DROP TABLE `#mysql50##sql-ib87-856498050`;The
#mysql50#prefix tells MySQL to ignorefile name safe encodingintroduced in MySQL 5.1. Enclosing the table name in backticks is required to perform SQL statements on table names with special characters such as “#”.
If an unexpected exit occurs during an in-place
ALTER TABLE operation that was
moving a table to a different tablespace, the recovery process
restores the table to its original location but leaves an
orphan intermediate table in the destination tablespace.
If MySQL exits in the middle of an in-place
ALTER TABLE operation on a
partitioned table, you may be left with multiple orphan
intermediate tables, one per partition. In this case, use the
following procedure to remove the orphan intermediate tables:
In a separate instance of the same MySQL version, create a non-partitioned table with the same schema name and columns as the partitioned table.
Copy the
.frmfile of the non-partitioned table to the database directory with the orphan intermediate tables.Make a copy of the
.frmfile for each table, and rename the.frmfiles to match names of the orphan intermediate tables (as described above).Perform a
DROP TABLEoperation (as described above) for each table.
If MySQL exits in the middle of a table-copying
ALTER TABLE operation
(ALGORITHM=COPY), you may be left with an
orphan temporary table that takes up space on your system. Also,
an orphan temporary table in an otherwise empty
general
tablespace prevents you from dropping the general
tablespace. This section describes how to identify and remove
orphan temporary tables.
Orphan temporary table names begin with an
#sql- prefix (e.g.,
#sql-540_3). The accompanying
.frm file has the same base name as the
orphan temporary table.
If there is no .frm file, you can
recreate it. The .frm file must have the
same table schema as the orphan temporary table (it must have
the same columns and indexes) and must be placed in the
database directory of the orphan temporary table.
To identify orphan temporary tables on your system, you can
query the Information Schema
INNODB_SYS_TABLES table. Look for
table names that begin with #sql. If the
original table resides in a
file-per-table
tablespace, the tablespace file (the
#sql-*.ibd file) for the orphan temporary
table should be visible in the database directory.
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE '%#sql%';
To remove an orphan temporary table, drop the table by issuing a
DROP TABLE statement, prefixing
the name of the table with #mysql50# and
enclosing the table name in backticks. For example:
mysql> DROP TABLE `#mysql50##sql-540_3`;
The #mysql50# prefix tells MySQL to ignore
file name safe encoding introduced in MySQL
5.1. Enclosing the table name in backticks is required to
perform SQL statements on table names with special characters
such as “#”.
If MySQL exits in the middle of an table-copying
ALTER TABLE operation on a
partitioned table, you may be left with multiple orphan
temporary tables, one per partition. In this case, use the
following procedure to remove the orphan temporary tables:
In a separate instance of the same MySQL version, create a non-partitioned table with the same schema name and columns as the partitioned table.
Copy the
.frmfile of the non-partitioned table to the database directory with the orphan temporary tables.Make a copy of the
.frmfile for each table, and rename the.frmfiles to match the names of the orphan temporary tables (as described above).Perform a
DROP TABLEoperation (as described above) for each table.
With innodb_file_per_table
enabled, the following message might occur if the
.frm or .ibd files (or
both) are missing:
InnoDB: in InnoDB data dictionary has tablespace id N,
InnoDB: but tablespace with that id or name does not exist. Have
InnoDB: you deleted or moved .ibd files?
InnoDB: This may also be a table created with CREATE TEMPORARY TABLE
InnoDB: whose .ibd and .frm files MySQL automatically removed, but the
InnoDB: table still exists in the InnoDB internal data dictionary.If this occurs, try the following procedure to resolve the problem:
Create a matching
.frmfile in some other database directory and copy it to the database directory where the orphan table is located.Issue
DROP TABLEfor the original table. That should successfully drop the table andInnoDBshould print a warning to the error log that the.ibdfile was missing.
This procedure describes how to restore orphan
file-per-table
.ibd files to another MySQL instance. You
might use this procedure if the system tablespace is lost or
unrecoverable and you want to restore .ibd
file backups on a new MySQL instance.
The procedure is not supported for
general
tablespace .ibd files.
The procedure assumes that you only have
.ibd file backups, you are recovering to
the same version of MySQL that initially created the orphan
.ibd files, and that
.ibd file backups are clean. See
Section 14.6.1.4, “Moving or Copying InnoDB Tables” for information about
creating clean backups.
Table import limitations outlined in Section 14.6.1.3, “Importing InnoDB Tables” are applicable to this procedure.
On the new MySQL instance, recreate the table in a database of the same name.
mysql> CREATE DATABASE sakila; mysql> USE sakila; mysql> CREATE TABLE actor ( actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, first_name VARCHAR(45) NOT NULL, last_name VARCHAR(45) NOT NULL, last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (actor_id), KEY idx_actor_last_name (last_name) )ENGINE=InnoDB DEFAULT CHARSET=utf8;Discard the tablespace of the newly created table.
mysql> ALTER TABLE sakila.actor DISCARD TABLESPACE;Copy the orphan
.ibdfile from your backup directory to the new database directory.$> cp /backup_directory/actor.ibd path/to/mysql-5.7/data/sakila/Ensure that the
.ibdfile has the necessary file permissions.Import the orphan
.ibdfile. A warning is issued indicating thatInnoDBtries to import the file without schema verification.mysql> ALTER TABLE sakila.actor IMPORT TABLESPACE; SHOW WARNINGS; Query OK, 0 rows affected, 1 warning (0.15 sec) Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './sakila/actor.cfg', will attempt to import without schema verificationQuery the table to verify that the
.ibdfile was successfully restored.mysql> SELECT COUNT(*) FROM sakila.actor; +----------+ | count(*) | +----------+ | 200 | +----------+