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.
What REPAIR TABLE actually covers
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 repairwp_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.
Telling a crashed MyISAM table from a corrupted InnoDB one
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.
Before anything else: take a cold copy
/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.
Three recovery paths, in rough order of preference
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 = 1BASH
# 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.sqlinnodb_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.
