Bali, Indonesia
Insights

REPAIR TABLE Won't Fix a Crashed InnoDB Table in MySQL or MariaDB

October 24, 2026
0:00
When a WordPress database starts throwing errors, the usual first move is REPAIR TABLE wp_posts; in phpMyAdmin, or mysqlcheck --repair from the shell. The command finishes quickly and reports no error, yet the site stays broken. The reason is simple: on InnoDB, the default storage engine for years in both MySQL and MariaDB, REPAIR TABLE does nothing. It says so in its output, but the message is easy to miss. This matters because most damaged tables on a modern hosting server are InnoDB. The repair step that people rely on doesn't touch them, so the real recovery work is still ahead.
REPAIR TABLE was built for storage engines that keep data and indexes in plain files with no transaction log. MySQL documents support for MyISAM, ARCHIVE, and CSV. MariaDB adds Aria, its crash-safe successor to MyISAM. On those engines, a crash during a write can leave an index file out of sync with the data file. REPAIR rebuilds the index from the data, and that usually resolves it. InnoDB works differently. It writes changes to a redo log before touching the data files and replays that log on startup after a crash. That process, called crash recovery, is the engine's built-in repair. It runs automatically every time the server starts. When crash recovery can't cope, the problem usually lies deeper, such as a damaged page on disk or a broken tablespace. A command that rebuilds MyISAM index files can't help with either. So on an InnoDB table, REPAIR TABLE returns a note instead of an error. mysqlcheck --repair is a wrapper that sends REPAIR TABLE to the server, so it returns the same note, one line per table. When it runs across a whole database, the useful lines get buried in a long list of OKs and notes.
BASH
# Read-only: list the engine of every table in a database
mysql -e "SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'wp_database';"

# Read-only: ask the server to check a single table (works on InnoDB)
mysql -e 'CHECK TABLE wp_database.wp_posts\G'

# Illustrative output format when REPAIR is run against an InnoDB table:
#    Table: wp_database.wp_posts
#       Op: repair
# Msg_type: note
# Msg_text: The storage engine for the table doesn't support repair
Replace wp_database with the real database name. CHECK TABLE does support InnoDB. What it does when it finds corruption depends on the version: newer releases mark the affected index as corrupted, while some older ones could stop the server deliberately. On a server that is already unstable, read the error log first, and treat CHECK TABLE as a confirmation step rather than the first probe.
The phrase "marked as crashed and should be repaired" causes a lot of the confusion. That error comes from MyISAM and Aria. If you see it, the table really does use one of those engines, and REPAIR TABLE is the right tool. Older WordPress installs, and tables created by plugins that set ENGINE=MyISAM explicitly, still turn up on servers fairly often. InnoDB problems look different. The server may refuse to start, restart in a loop, or log lines about page corruption, checksum mismatches, or assertion failures in the error log. Sometimes only one table fails and returns an error saying the table doesn't exist in the engine, even though its files are still in the data directory. The error log is the place to start, not phpMyAdmin. Its location depends on the distro and the control panel. The log_error variable shows the path when the server is running, and the systemd journal for the database service usually holds it when the server won't start. At the support desk, this is usually the first thing worth confirming before anyone touches the server: which engine the broken table uses, and whether the database server is running at all. Those two answers decide which of the paths below apply.
Every InnoDB recovery path involves some risk of making things worse. Before you change any settings, stop the database service and copy the whole data directory to another disk or location. This is called a cold copy. The data directory is often /var/lib/mysql, but confirm it with the datadir setting for your setup. Check that the copy is complete before you continue. This copy is your undo button. Without it, a wrong step such as a high innodb_force_recovery level can turn a recoverable problem into permanent data loss.
The right choice depends on whether the server runs, how much is damaged, and how recent your backup is. Rebuild the table. If the server runs normally and the damage is limited to one table, often a secondary index, rebuilding it can be enough. ALTER TABLE wp_posts ENGINE=InnoDB; rewrites the table from the readable data. OPTIMIZE TABLE on InnoDB maps to the same rebuild plus an ANALYZE. On a large table this takes time and needs free disk space roughly the size of the table. If the rebuild fails because the server can't read the rows, move on to a dump. Force recovery, then dump and reload. If the server won't start, or crashes as soon as it touches the damaged table, innodb_force_recovery tells InnoDB to skip some of its startup checks so you can get in and export data. It's an emergency setting, not a fix. Levels run from 1 to 6. When the value is above 0, InnoDB blocks normal writes, so the server is only useful for reading data out. Start at 1 and raise the value one step at a time, only if the server still won't start. Values of 4 and above can permanently corrupt data files. Use those levels only when you already have a cold copy and no better option.
INI
# Add under [mysqld] in the server config, then restart the service.
# File location varies: /etc/my.cnf, /etc/mysql/my.cnf, or a file in conf.d
[mysqld]
innodb_force_recovery = 1
Once the server is up, dump what you can, ideally the whole affected database, or at least the tables that matter.
BASH
# Export one database while the server runs in force recovery mode
mysqldump --single-transaction --routines --triggers wp_database > /root/wp_database-recovery.sql

# If the full dump fails on one table, dump the readable tables individually
mysqldump wp_database wp_options wp_users wp_usermeta > /root/wp_core-tables.sql
Check that each dump file ends cleanly. A dump that stops in the middle of a table means that table is still unreadable at the current level. Next, remove the innodb_force_recovery line and restart normally. Depending on how bad the damage is, either drop and recreate the affected database or rebuild the instance from scratch, then import the dump. Leaving force recovery enabled in production is a common mistake, because writes stay blocked and the site keeps failing in new ways. Restore from backup. Restoring is often the better choice, even if it feels like a step back. If the damage spans many tables, if you need level 4 or higher, or if the dumps keep failing partway through, a clean backup is usually faster and safer than piecing together partial exports. The cost is any data written since that backup. If binary logging was enabled and the logs are intact, you may be able to replay changes made after the backup and close that gap. That only works if the logs were managed well beforehand. Unmanaged binary logs filling a disk are their own cause of outages, as covered in Why MySQL Crashes When Binary Logs Silently Fill Your Disk. A reasonable rule of thumb is to try a rebuild when the server is healthy and one table misbehaves. Use force recovery when the server won't start but recent data matters more than a fast restore. Go straight to the backup when the damage is widespread or the backup is recent enough that the lost window is acceptable.
InnoDB doesn't usually corrupt itself without a cause. Common causes include the host losing power or the VM being killed without a clean shutdown, a full disk during heavy writes, failing storage, and filesystem problems underneath the database. Settings that trade durability for speed can also leave the engine without the information it needs to recover. If you restore the data but don't look for the cause, the same problem often returns. After recovery, check the kernel log and storage health for disk errors, confirm there is free space on the data volume, and look at how the server last shut down. If any tables still use MyISAM, converting them to InnoDB removes the tables that genuinely need REPAIR TABLE. Do that during a quiet window, after a backup. In practice, check the engine before you type REPAIR. If the table is MyISAM or Aria, REPAIR is the right tool. If it's InnoDB, read the error log, take a cold copy, and then choose between a rebuild, a force-recovery dump, or a restore based on how much is damaged and how fresh your backup is. The step that saves the most data is usually the cold copy you take before changing anything.