TL;DR
Copying/moving MySQL tables by altering the underlying files is possible in some conditions but it is highly unrecommended.
Always use MySQL
commands to do it.
The .frm
file contains only the table definition. The data and the indexes are stored in other files and they depend on the storage engine of the table.
Several excerpts from the official documentation:
15.2 The MyISAM Storage Engine
Each MyISAM
table is stored on disk in three files. The files have names that begin with the table name and have an extension to indicate the file type. An .frm
file stores the table format. The data file has an .MYD
(MYData) extension. The index file has an .MYI
(MYIndex) extension.
14.1 Introduction to InnoDB
By default, with the innodb_file_per_table
setting enabled, each new InnoDB
table and its associated indexes are stored in a separate file. When the innodb_file_per_table
option is disabled, InnoDB stores all its tables and indexes in the single system tablespace, which may consist of several files (or raw disk partitions).
14.2.15.1 Role of the .frm File for InnoDB Tables
MySQL stores its data dictionary information for tables in .frm
files in database directories. Unlike other MySQL storage engines, InnoDB
also encodes information about the table in its own internal data dictionary inside the tablespace. When MySQL drops a table or a database, it deletes one or more .frm
files as well as the corresponding entries inside the InnoDB
data dictionary. You cannot move InnoDB
tables between databases simply by moving the .frm
files.
14.12 InnoDB Startup Options and System Variables
innodb_file_per_table
When innodb_file_per_table
is enabled (the default in 5.6.6 and higher), InnoDB
stores the data and indexes for each newly created table in a separate .ibd
file, rather than in the system tablespace
.
MySQL Glossary
system tablespace
One or more data files (ibdata
files) containing the metadata for InnoDB-related objects (the data dictionary), and the storage areas for the undo log, the change buffer, and the doublewrite buffer. Depending on the setting of the innodb_file_per_table
, when tables are created, it might also contain table and index data for some or all InnoDB
tables. The data and metadata in the system tablespace apply to all the databases in a MySQL instance.
Prior to MySQL 5.6.7, the default was to keep all InnoDB tables and indexes inside the system tablespace, (...) In MySQL 5.6.7 and higher, the default is file-per-table
mode, where each table and its associated indexes are stored in a separate .ibd
file.
Let's draw some (partial) conclusion
Before anything else you have to stop the MySQL server (to be sure all the data is safely stored into files).
If the table you want to copy uses the MyISAM
engine then you need to copy/rename the .frm
, .MYD
and .MYI
files having the same name as the table.
If the table uses the InnoDB
engine and at the moment when it was created the innodb_file_per_table
setting was ON
then you need to copy/rename the .frm
and .ibd
files having the same name as the table.
If the table uses the InnoDB
engine and it was created while the innodb_file_per_table
setting was OFF
then you cannot copy or move the table data from outside MySQL.
If the table uses the MEMORY
table then it's enough to copy the .frm
file and restart the server. The table data and indexes are stored in memory, there is no file for them and the source table will be empty after the server restart, so you get an exact copy of an empty table ;-)
But wait, there is more!
MySQL implements several other storage engines that are probably less used than the ones mentioned above. Each of them has its own rules of storing the data in files.
And more
If the server you want to hack this way is part of a replication cluster the changes you do either are ignored (do not propagate to the other servers in the cluster if you change a slave server) or break the replication (the slave servers are required to query and update a table they don't have, if you change the master server).
The conclusion
Even if, in certain conditions, copying or moving a table by changing the underline files is possible, it is strongly not recommended.
The correct (and many times the only) way to copy a table is to use the commands provided by MySQL.
13.1.14 CREATE TABLE Syntax
Use LIKE
to create an empty table based on the definition of another table, including any column attributes and indexes defined in the original table:
CREATE TABLE new_tbl LIKE orig_tbl;
The copy is created using the same version of the table storage format as the original table. The SELECT
privilege is required on the original table.
You can then use:
INSERT INTO `new_tbl` SELECT * FROM `orig_tbl`
to copy the data.
Another way
An alternative way to copy a table without writing SQL commands is to export the table definition and data using mysqldump
, open the export file in a text editor, change the table name in all the places where it appears, save the file and import it into the database using the mysql
command line tool (or other MySQL
client).