Safely Repair and Recover a Corrupted MySQL Database Table
Corrupted MySQL tables can lock out apps and sites overnight. Learn unique crash symptoms, safe DIY repair commands, and when to book Fixwebnode before data loss spreads.
If your site or business app suddenly throws table errors, refuses queries, or marks a MySQL table as crashed, this guide walks you through safe repair and recovery steps you can run yourself—and when to stop and get specialist help.
Small businesses and homeowners running WordPress, billing tools, or internal apps on a VPS often hit MySQL table corruption after power loss, full disks, killed mysqld processes, or failed upgrades. Below you will diagnose three distinct failure patterns, run real CLI checks, and recover tables without guessing. When the damage is deeper than a single table, Fixwebnode’s MySQL table repair and recovery service can take over with a controlled restore path.
We support clients across our service areas with the same runbook mindset: backup first, verify engine type, repair only what is safe, then prove the table is clean before you reopen the app.
Why safe MySQL table repair matters
MySQL stores table data and indexes in engine-specific files. A half-written page, a torn redo log, or a mismatched .frm definition can make one table unreadable while the rest of the instance still starts. Rushing a repair without a backup can turn a recoverable crash into permanent row loss. The goal is always: freeze writes if needed, copy files or dump what still works, identify MyISAM vs InnoDB, apply the matching repair path, then validate with CHECK TABLE and application smoke tests.
Assumptions for the steps below: you have shell access (SSH) to a Linux host, MySQL or MariaDB 5.7+/10.x+, and either root OS access or a DB user with RELOAD, PROCESS, and table-level privileges. Replace placeholders like your_db and your_table with real names.
Common issues with corrupted MySQL tables
These problems look similar in the app (“table doesn’t exist”, “can’t open”, 500 errors) but have different root causes and fix paths.
- MyISAM crash after unclean shutdown — Error log shows “Table is marked as crashed and should be repaired”;
SELECTfails with Errcode 144 or 145; only MyISAM tables are affected. - InnoDB tablespace or page corruption — Server may start, but queries on one table return “ERROR 1034” / “Incorrect key file” / “Tablespace is missing”, or InnoDB aborts with space ID mismatches in the error log.
- Orphaned definition vs data files (.frm / .ibd mismatch) — After a failed restore, manual file copy, or partial DROP, MySQL lists the table but cannot open it, or
SHOW TABLE STATUSshows wrong engine/row estimates and file-level errors.
Issue 1 — Repair a crashed MyISAM table
MyISAM keeps data in .MYD and indexes in .MYI. An abrupt kill or full disk often marks the table crashed. DIY repair is usually safe after a file-level backup.
Step 1 — Confirm engine and symptoms
sudo systemctl status mysql sudo tail -n 100 /var/log/mysql/error.log mysql -u root -p -e "SHOW TABLE STATUS FROM your_db LIKE 'your_table'\G"Look for Engine: MyISAM and crash messages naming that table.
Step 2 — Stop writes and back up table files
mysql -u root -p -e "FLUSH TABLES WITH READ LOCK;" # In a second session, locate datadir mysql -u root -p -Nse "SELECT @@datadir" sudo systemctl stop mysql sudo mkdir -p /root/mysql-table-backup sudo cp -a /var/lib/mysql/your_db/your_table.* /root/mysql-table-backup/ sudo systemctl start mysqlPaths may be /var/lib/mysql on Debian/Ubuntu or under a custom datadir. Copy every file matching the table name.
Step 3 — Online REPAIR (preferred first attempt)
mysql -u root -p your_db -e "CHECK TABLE your_table EXTENDED;" mysql -u root -p your_db -e "REPAIR TABLE your_table EXTENDED;" mysql -u root -p your_db -e "CHECK TABLE your_table EXTENDED;" mysql -u root -p your_db -e "ANALYZE TABLE your_table;"Expect status: OK on the final check. If REPAIR reports that the table was repaired, re-run application queries that previously failed.
Step 4 — Offline myisamchk if online repair fails
sudo systemctl stop mysql sudo myisamchk -r -q /var/lib/mysql/your_db/your_table # If still dirty, force a rebuild of indexes: sudo myisamchk -r -f /var/lib/mysql/your_db/your_table sudo chown mysql:mysql /var/lib/mysql/your_db/your_table.* sudo systemctl start mysql mysql -u root -p your_db -e "CHECK TABLE your_table EXTENDED;"When to call Fixwebnode: repair loops without OK, myisamchk reports unrecoverable records you cannot afford to drop, or multiple MyISAM tables crashed together after disk failure. Book a guided recovery via the corrupted MySQL table recovery page before running destructive -f passes on production data.
Issue 2 — Recover from InnoDB table or page corruption
InnoDB corruption is different: you must not run MyISAM tools on it. Symptoms often include forced InnoDB recovery needs, missing tablespace, or assertion failures in the error log. DIY is limited to dump-and-rebuild when the server can still read rows under a raised innodb_force_recovery level.
Step 1 — Capture evidence and full backup of still-readable data
sudo tail -n 200 /var/log/mysql/error.log mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" | head -n 80 sudo systemctl stop mysql sudo tar -czf /root/mysql-datadir-pre-recovery.tgz -C /var/lib mysql sudo systemctl start mysqlStep 2 — Identify whether the table is still selectable
mysql -u root -p -e "SELECT COUNT(*) FROM your_db.your_table;" mysql -u root -p -e "CHECK TABLE your_db.your_table;"If SELECT works, dump immediately:
mysqldump -u root -p --single-transaction --routines --triggers your_db your_table > /root/your_table_salvage.sql gzip -9 /root/your_table_salvage.sqlStep 3 — Controlled innodb_force_recovery (read-only salvage only)
Only if the server will not start cleanly or the table is unreadable. Edit the server config (Ubuntu example):
sudo cp /etc/mysql/mysql.conf.d/mysqld.cnf /root/mysqld.cnf.bak sudo sed -n '1,80p' /etc/mysql/mysql.conf.d/mysqld.cnf echo '[mysqld] innodb_force_recovery = 1' | sudo tee /etc/mysql/mysql.conf.d/recovery.cnf sudo systemctl restart mysqlTry levels 1 → 2 → 3 → 4 only as needed. At level 4+ InnoDB is treated as read-only; do not run updates. After each restart:
mysqldump -u root -p --single-transaction --skip-lock-tables your_db your_table > /root/your_table_fr.sql || true mysqldump -u root -p --single-transaction your_db > /root/full_db_fr.sql || trueStep 4 — Rebuild the table on a clean engine
# Remove force_recovery so normal writes work again sudo rm -f /etc/mysql/mysql.conf.d/recovery.cnf sudo systemctl restart mysql mysql -u root -p -e "DROP TABLE IF EXISTS your_db.your_table_bad;" # Prefer rename-aside if DROP is risky in your process, then: mysql -u root -p your_db < /root/your_table_salvage.sql mysql -u root -p -e "CHECK TABLE your_db.your_table EXTENDED; SELECT COUNT(*) FROM your_db.your_table;"If dumps fail at every recovery level, stop DIY. Forcing higher levels or deleting ibdata1 without a plan destroys redo history.
When to call Fixwebnode: InnoDB refuses all dumps, multiple tablespaces are inconsistent, or the instance crash-loops even at recovery level 1. Related OS-level breakage (broken package sources blocking MySQL package fixes) is common on neglected VPS hosts—see parallel Linux recovery help such as Fix Corrupted Linux APT Sources.list – Alabama expert support and Fix Linux Corrupted APT sources.list – Connecticut expert when package repair is blocking DB tooling installs.
Issue 3 — Fix orphaned .frm / .ibd definition mismatches
This shows up after someone copied only some table files, restored from a partial snapshot, or interrupted an ALTER. MySQL “knows” the table name but cannot attach the tablespace.
Step 1 — Inventory files vs dictionary
mysql -u root -p -Nse "SELECT @@datadir" ls -la /var/lib/mysql/your_db/ | egrep 'your_table|db.opt' mysql -u root -p -e "SHOW TABLES FROM your_db LIKE 'your_table';" mysql -u root -p -e "SHOW CREATE TABLE your_db.your_table\G"Note missing .ibd, leftover .frm (older layouts), or a tablespace error on SHOW CREATE.
Step 2 — Discard/import tablespace path (InnoDB file-per-table)
Only when you have a known-good matching .ibd from backup taken with the same schema version:
mysql -u root -p your_db -e "SHOW VARIABLES LIKE 'innodb_file_per_table';" # Create an empty table with IDENTICAL structure from a known-good CREATE script: mysql -u root -p your_db -e "CREATE TABLE your_table_new LIKE your_table_backup_clone;" mysql -u root -p your_db -e "ALTER TABLE your_table_new DISCARD TABLESPACE;" sudo systemctl stop mysql sudo cp /root/good-backup/your_table.ibd /var/lib/mysql/your_db/your_table_new.ibd sudo chown mysql:mysql /var/lib/mysql/your_db/your_table_new.ibd sudo systemctl start mysql mysql -u root -p your_db -e "ALTER TABLE your_table_new IMPORT TABLESPACE;" mysql -u root -p your_db -e "CHECK TABLE your_table_new EXTENDED;" mysql -u root -p your_db -e "RENAME TABLE your_table TO your_table_old_broken, your_table_new TO your_table;"Schema must match exactly (column order, types, row format). A mismatched import fails or corrupts silently—verify row counts against an old dump if you have one.
Step 3 — If only MyISAM files were half-copied
sudo systemctl stop mysql sudo ls -la /root/mysql-table-backup/ sudo cp -a /root/mysql-table-backup/your_table.MYD /var/lib/mysql/your_db/ sudo cp -a /root/mysql-table-backup/your_table.MYI /var/lib/mysql/your_db/ sudo cp -a /root/mysql-table-backup/your_table.frm /var/lib/mysql/your_db/ 2>/dev/null || true sudo chown mysql:mysql /var/lib/mysql/your_db/your_table.* sudo myisamchk -r -f /var/lib/mysql/your_db/your_table sudo systemctl start mysql mysql -u root -p your_db -e "CHECK TABLE your_table;"Step 4 — Application verification
mysql -u root -p -e "SELECT COUNT(*) AS rows_now FROM your_db.your_table;" mysql -u root -p -e "SHOW TABLE STATUS FROM your_db LIKE 'your_table'\G"Then hit the real app pages that use that table (login, checkout, admin list). Compare counts to your last known good backup report.
When to call Fixwebnode: you lack a schema-matched .ibd, import fails with space ID errors, or the only copy lives inside a damaged snapshot. Transportable tablespace recovery is easy to get wrong once; a specialist prevents a second overwrite of the only good file set.
When DIY is enough vs when to book Fixwebnode
DIY is reasonable when: a single MyISAM table is marked crashed, you already have file copies under /root, CHECK TABLE returns OK after REPAIR, and row counts match expectations. Also reasonable when InnoDB still allows mysqldump --single-transaction without force recovery.
Book Fixwebnode when: the error log shows InnoDB assertion failures, several databases failed together, the disk that holds the datadir is failing, binary backups are untested, or you are unsure whether the table is MyISAM or InnoDB. Home labs can experiment; production order and customer data should not. Geography-wise we work with clients mapped under our published service areas—remote SSH sessions follow the same backup-first discipline described above.
Do not delete ibdata1, do not run myisamchk on InnoDB files, and do not raise innodb_force_recovery above the minimum needed for a dump. Those three mistakes cause most irreversible DIY outcomes we later reverse-engineer.
Closing: get a safe recovery path
Corrupted MySQL tables are recoverable more often than they first appear—if you back up files first, match the tool to the storage engine, and verify with CHECK TABLE plus real application reads. Use the MyISAM repair path for crashed .MYI indexes, dump-and-rebuild under careful force recovery for InnoDB, and schema-matched tablespace import only when definitions align.
If you want a second set of eyes before the next restart, start a conversation through How to Safely Repair and Recover a Corrupted MySQL Database Table on Fixwebnode. Tell us the exact error text, engine type, and whether you already have a datadir tarball—we will outline the safest next step for your instance without marketplace noise or guesswork.