Not all tables showing up when recovering MYSQL - mysql

I am recovering a missing mysql db with tables and have the frm files and ibdata1.
I have used innodb_file_per_table to make each DB have its own data file and tests show that new DB now use this system when created.
I noticed that when I to view the newly imported frms and data or write any SQL against them, they aren't being found. Several 'views' are available, but no tables.
If I run check table sometablename, I get that the table doesn't exist.
If I try to create a table with the same name, I get that the table already exists.
I have stopped and started the MYSQL service several times, hoping it would pick up the new frms, but nothing.
Any idea?

You can't restore a database by simply loading in the contents of the database directory. InnoDB stores other information in some master files located in the main MySQL data directory.
The only reliable method of recovering all data is to either use a mysqldump and restore procedure, or to FLUSH WITH WRITE LOCK before copying the entire contents of the MySQL data directory. This method is not recommended for production systems as it locks the entire database for the duration of this operation.

Related

Restoring a single MyISAM database under MySQL 8 from a physical backup

this isn't my exact situation but close enough for description.
On a MySQL 8.0.28 instance on an ubuntu 22.08 server, I have a database 'important' that contains only MyISAM tables. Within MySQL I:
DROP DATABASE important;
then continue to 'do stuff' with other databases etc. Some time later, I decide I want that 'important' database back (without restoring other databases). Luckily I have a physical backup of the MySQL data folder, specifically including the 'important' directory.
If I stop the server, copy the 'important' directory back in place, then restart the server I hoped (and was the case under MySQL 5) that the database would re-appear, but it doesn't.
As far as I can sell, MySQL 5 used to physically scan the directory to look for databases whereas MySQL 8 seems to have a separate idea of what databases exist. To clarify, I am only using MySQL 8.0.28 in this scenario - the backup was made under the same version as I'm restoring to.
My question is, how can I make this database reappear? Perhaps that's "How can I make MySQL 8 rescan its database of databases"?
I think you're in uncharted territory.
It's true that in MySQL 5.x, you could create a schema simply with mkdir, creating a subdirectory under the data directory. Within that directory, each MyISAM table has three files: tablename.MYD, tablename.MYI, and tablename.frm. The frm file has metadata about the table and its columns, so the MyISAM storage engine could discover new tables simply by reading their respective frm file.
This was not possible for InnoDB in 5.x, because InnoDB had an internal data dictionary stored in the ibdata1 tablespace in the data directory. The data dictionary had to maintain duplicate metadata about InnoDB tables.
In MySQL 8.0, they eliminated frm files completely. Tables of all storage engines are managed by the InnoDB data dictionary. There is no interface to the data dictionary besides DDL statements like CREATE/ALTER/DROP. There are several benefits to this change.
This means you can't use external shell commands like mkdir and cp to create schemas and tables. You have to use DDL to communicate to the data dictionary. It's not only stored on disk in the InnoDB tablespace, but it's also cached as objects in the MySQL Server process. Using DDL updates both.
I have not tried this with MyISAM tables (I haven't used MyISAM tables if I can avoid it for over ten years), but in theory you could use CREATE SCHEMA and CREATE TABLE to recreate empty tables that match the definition of the tables you're restoring. Then outside of MySQL, use cp to copy the tables you want to restore over the empty data and index files. I would shut down MySQL Server before doing this, to hopefully avoid any race conditions or conflicting with file caches.
I have no idea if that will work. I would test these steps first on a test instance (not your production instance).

InnoDB: Cannot open table from the internal data dictionary of InnoDB though the .frm file for the table exists

I am running Windows 10 with XAMPP and several dozen Drupal sites installed on localhost. Everything has been working fine for months.
This morning I performed a Windows restore from a restore point two days ago to get rid of an unwanted Windows update. After I did that, my MySQL stopped working. I tried deleting the file ibdata1 (I now know that that was a bad idea), but when things got worse, I restored the initial ibdata1 that I'd deleted. All the table data (.frm and .ibd files) is still in C:\xampp\mysql\data. Now MySQL will at least start, but all the tables are "gone"... I can load phpMyAdmin in the browser, and when I drop down the databases at left, all the tables show... but when I try to click on one, it tells me "table not found."
In mysql_error.log there are several errors like InnoDB: Cannot open table mysql/slave_master_info from the internal data dictionary of InnoDB though the .frm file for the table exists. There is a URL mentioned in the error message that supposedly tells you how to resolve this issue, but it is uninformative.
I don't think ibdata1 is corrupted... and all the articles regarding recovering data are complicated to a degree that is insanely out of proportion to the problem. No one has a simple spelled-out solution. Am I Googling wrong? This has happened to me at least twice before, and each time the problem spontaneously resolved itself before I was able to start following the 10-hour-long procedures I found online. Not this time, unfortunately. Surely I'm missing something simple. I had hundreds and hundreds of tables in a few dozen databases, and it seems hopeless to try to find the schema for each one and manually plug it in, which is what most recovery articles seem to suggest.
Shouldn't the database just know how to read the .frm and .ibd files, and, you know... work? It feels like there's just one value out of place somewhere, and if I could just find it, everything would just "pop" back into place.
What did the work for us was this link (Restoring Orphan File-Per-Table ibd Files).
In brief, you do:
ALTER TABLE ..... DISCARD TABLESPACE;
For each affected table.
Then, for each affected table:
ALTER TABLE .... IMPORT TABLESPACE; SHOW WARNINGS;
You could do that on the same schema or create a new schema in other database and copy all *.ibd files. In this case:
Create the new schema with table definitions.
Do the discard tablespace for all tables.
Copy the new *.ibd files to the right folder of new schema.
Do de import tablespace for all tables.
IMPORTANT! It's better that the new schema has the same name as the old one.
What worked for me:
https://dba.stackexchange.com/a/42932
My dbs was InnoDB, so there is a problem with id and when upgrading the macos, I got this. I will quote the main part:
You must have:
-ibdata1
-ib_logfile0
-ib_logfile1
-.FRM files from your mysql_database folder
-Fresh installation of MAMP / MAMP Pro that you are willing to destroy (if need be)
SSH into your web server (dev, production, no difference) and browse to your mysql folder (mine was at /var/lib/mysql for a Plesk
installation on Linux)
Compress the mysql folder
Download an archive of mysql folder which should contain all mySQL databases, whether MyISAM or innoDB (you can scp this file, or move
this to a downloadable directory, if need be)
Install MAMP (Mac, Apache, MySQL, PHP)
Browse to /Applications/MAMP/db/mysql/
Backup /Applications/MAMP/db/mysql to a zip archive (just in case)
Copy in all folders and files included in the archive of the mysql folder from the production server (mt Plesk environment in my case)
EXCEPT DO NOT OVERWRITE:
-/Applications/MAMP/db/mysql/mysql/
-/Applications/MAMP/db/mysql/mysql_upgrade_info
-/Applications/MAMP/db/mysql/performance_schema
In my case, I was restoring the backup (done by galera-arbitrator and xtrabackup. Using the first one we took state-snapshot and using the last one we backed up the physical data) for Percona_XtraDB_Cluster. So, after placing the backed up data to the dir /var/lib/mysql of the new mysql server, we did the following select query and got error.
$ mysql -uroot -p$MYSQL_ROOT_PASSWORD -h<NEW_SERVER_HOST_NAME> -e 'show columns from <MY_DB>.<MY_TABLE>'
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1146 (42S02) at line 1: Table 'playground.equipment' doesn't exist
And the server log was:
[Warning] InnoDB: Cannot open table <MY_DB>/<MY_TABLE> from the internal data dictionary of InnoDB though the .frm file for the table exists. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.
We just restarted the container the new data. That's it
Just rename slave_master_info.frm to slave_master_info.BAK and that's it. Restart the mysql service.

Why does renaming a database require copying data?

Using phpMyAdmin, I tried to rename my 6GB database, only to discover that the operation takes a couple of hours. According to this SO question, it sounds like renaming a database requires creating a new database and copying the data over. Why isn't the name just a pointer to some text that can be changed at will?
Edit on 14 March 2016
I originally accepted Gandalf's answer because I could not replicate the DB renaming taking so long. But this long renaming process is happening again. Here is a screenshot of phpMyAdmin hanging:
And here is a screenshot of the results from SHOW PROCESSLIST when connecting directly to the MySQL server:
It looks like the query is spinning on adding a constraint. I'm pretty sure the command that phpMyAdmin ran was:
RENAME TABLE harmonizome_temp TO harmonizome;
This is probably necessary to ensure database integrity if there's an error during the process.
Information about the database is stored in both the filesystem (each database is a directory) and also in the INFORMATION_SCHEMA database. When you rename a database, both have to be updated. If it simply renamed the directory and updated INFORMATION_SCHEMA, there would be a period of time when these are out of sync. And if the process is aborted at this stage, the database will be corrupted.
By copying the data, it can ensure that they're never out of sync. The old directory is not deleted until after everything INFORMATION_SCHEMA is updated to refer to the new database name. If the process is aborted in the middle, you'll have duplicate data in the filesystem, but INFORMATION_SCHEMA will point to one or the other (a transaction can ensure that everything in INFORMATION_SCHEMA is updated atomically).

Restoring MySQL Databases when reinstalling Wamp

I am attempting to restore my old databases to a new Wamp installation. However, I did not take a backup of Mysql files before I did this. Thankfully the uninstallation has not deleted all the files, but in my data folder I have :
1) All the databases (As folders)
2) auto.cnf
There are no ib* files in the old folder. Is it still possible to restore my databases somehow?
I have tried to replace the entire mysql5.6.17 folder (there has been no change of version between the installations), but Wamp remains orange and never turns green.
If I replace only the data folder, the MySQL service starts, I can see the databases, but not the tables.
If I change the path in my.ini to point to the old wamp's data folder, I cannot see the old databases at all.
EDIT : Was experimenting a bit, copying the database folders directly into the new Wamp's data folder allows me to get a list of all the tables properly, but there is no actual data in the tables, and trying to query it using MySQLWorkbench gives me the error :
Error Code: 1146. Table 'testdb.users' doesn't exist
EDIT 2 : Found this in the error log file in my data folder :
2014-08-03 06:24:46 25164 [Warning] InnoDB: Cannot open table testdb/users from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem.
As I thought, its a problem with InnoDB's own mapping. Is there a way to resolve this manually?
If you created an INNODB database, and made no other config changes to store the actual data in seperate table spaces then all the actual data for that INNODB databases will have been stored in the \wamp\bin\mysql\mysql5.6.17\ibdata1 file.
If you do not have that file from the old install then your data is lost.
There will also be info in a \wamp\bin\mysql\mysql5.6.17\data\DATA_BASE_NAME\ folder, one .frm file for each table that was in the database, but this is basically just schema information and not actual data.
For future reference, InnoDB Backup and Recovery
GOLDEN RULE:
Always backup database (from phpmyadmin) before major changes.. better to spend 1 minute for that, than going into trouble..
How to Copy data folder
If you want to copy the database, then INSTALLATION/mysql versions should be same.. then rename newly installed data folder to i.e. data_my_old,so now there you can place the backuped data folder (it should contain ibdata1 file).
Depends on innodb_file_per_table setting.
If it was OFF then all your tables were in ibdata1. Now you have quite new ibdata1 (since you see errors "Cannot open table testdb/users from the internal data dictionary", that means InnoDB runs fresh new dictionary). That means that now the data is somewhere on the disk. The recovery is quite difficult and requires a lot of tedious work. You need to take an image of the disk, scan it with stream_parser to find InnoDB pages, then recover the InnoDB dictionary, then find index_id of every table and if the stream_parser has found this index run c_parser to extract records from the index.
If innodb_file_per_table was ON and you do see .ibd files in the databases directories then recovery is much easier. First, you may try to reconnect individual ibd files with ibdconnect or extract records from the ibd files with stream_parser/c_parser.
The mentioned tools are part of TwinDB data recovery toolkit
i have just done a google search and found this....
Go to C:\wamp\bin\mysql\mysql5.5.24\data
Find a file called "mysql-bin.index"
Rename that file to "mysql-bin.index-corrupt"
Restart the server and it will work fine, all your database will be where you left them.

Fastest way to reload mysql databases in perl

I have a script that needs to add data to a folder created in the mysql data folder and then in some way force the mysql server to reload the data so the database reliably shows up. I am currently using a system call to the /etc/init.d/mysql script to restart the server but this is quite slow, I couldn't find anyhting in mysql that would reload the database through a query of some kind.. I was just wondering if there was a way to do this that was slightly quicker?
This depends on the storage engine you're using.
MyISAM tables will be reloaded automatically as soon as the table is next touched by MySQL (obviously, you need to make sure the .MYI, .MYD and .frm files are consistent).
InnoDB is a bit more complex, and depends on whether it's a traditional configuration with all tables in the same tablespace, or if you're using innodb_file_per_table. With the former, you pretty much have to restart the server. With file-per-table, you can copy individual .ibd files, but then you have to use an ALTER TABLE statement to import that tablespace.
See here for information on working with individual .ibd files without restarting the server.
This page is also useful for seeing how to move InnoDB data from place to place.
What do you mean by 'quite slow'?
You could do a dump/load of the new db in a one named orginal_db_name_temp, rename the original DB, and then rename orginal_db_name_temp to orginal_db_name - then you will have your new DB in place.
However, I don't know which method is faster by your means - because a dump&load roundtrip will be probably slower than a file-copy. But renaming the DBs will probably be faster than restarting the server