Cause #1: You Skipped mysql_upgrade or Ran the Wrong Version
The most common reason for this error is that you upgraded your MySQL binaries but never ran mysql_upgrade (or ran an old version of it). MySQL 8.0 introduced a new data dictionary, and the system tables like mysql.plugin are now stored differently. If you jump from 5.7 to 8.0 without letting MySQL rebuild those tables, the server refuses to start and throws Error 1146.
Here's the thing: in MySQL 8.0, mysql_upgrade is actually deprecated—you don't need to run it manually if you let the server initialize properly. But if you upgraded in-place (e.g., using rpm -U or apt upgrade) and the post-install scripts didn't trigger, you're stuck.
The Fix
- Stop the MySQL service if it's running (it probably isn't).
- Back up your data directory. Just in case.
cp -a /var/lib/mysql /var/lib/mysql_backup - Start MySQL with the
--skip-grant-tablesoption to bypass the missing table check:
mysqld --skip-grant-tables --user=mysql &
This lets the server start without trying to load the plugin table. Then run:
mysql_upgrade -u root -p
If you get an error about mysql_upgrade not being found, you're using a 5.7 client—make sure your PATH points to the 8.0 installation (/usr/local/mysql/bin or similar).
After it finishes (it'll take a while), stop the server and start it normally:
mysqladmin shutdown
systemctl start mysql
That usually fixes it. If not, move on to cause #2.
Cause #2: Incompatible Data Dictionary After a Failed Upgrade
Sometimes the upgrade partially completes, leaving the data dictionary in a weird state. You might see errors like Table 'mysql.plugin' doesn't exist but also other corruption messages. This happens when the upgrade process crashes mid-way, or when you copy data files from a 5.7 install into an 8.0 data directory.
The mysql.plugin table is one of the first system tables MySQL checks on startup. If the dictionary says it should exist but the actual .ibd file is missing or corrupt, the server bails.
The Fix
I don't like this fix, but it works: force InnoDB recovery to let the server start, then rebuild the table.
- Add this to your
my.cnfunder[mysqld]:
innodb_force_recovery=1
Start MySQL. If it starts, great. Now run mysql_upgrade again. But here's the catch—with innodb_force_recovery set to anything above 0, you can't write to InnoDB tables. So you'll need to:
- Stop the server, remove the
innodb_force_recoveryline, and restart. - If it still won't start, bump the recovery level up to 6 (the max). This disables most background operations, but it often lets the server start long enough to export data.
If you manage to get in, dump everything with mysqldump and reimport into a fresh 8.0 install. That's the nuclear option, but it's the only way to be sure your data dictionary is clean.
Cause #3: Permissions or Ownership Issues on the Data Directory
This one's sneaky. If the mysql user doesn't have read/write access to the data directory (or the mysql.plugin.ibd file specifically), MySQL can't open the table. You'd think the error would be about permissions, but it often surfaces as Table 'mysql.plugin' doesn't exist because the server can't even see the file.
I saw this happen on a CentOS 7 server after a partial restore from a backup—the file permissions got messed up.
The Fix
- Check ownership:
ls -la /var/lib/mysql/mysql/plugin.*. They should be owned bymysql:mysql. - Fix it:
chown -R mysql:mysql /var/lib/mysql - While you're at it, verify the file exists:
ls -la /var/lib/mysql/mysql/plugin.ibd. If it's missing, you might have to restore it from a backup or reinitialize.
If the file is truly gone, and you don't have a backup, you can create a fresh MySQL data directory by moving the old one aside and initializing a new one:
mv /var/lib/mysql /var/lib/mysql_old
mkdir /var/lib/mysql
chown mysql:mysql /var/lib/mysql
mysqld --initialize-insecure --user=mysql
That gives you a clean install, but you'll lose all databases unless you have a dump. That's a hard lesson, but it's better than being stuck in a boot loop.
Quick Reference Table
| Cause | Symptom | Fix |
|---|---|---|
| Missing mysql_upgrade | Error right after upgrade, before any other issues | Run mysql_upgrade (or restart with --skip-grant-tables first) |
| Corrupt data dictionary | Error plus other corruption messages, partial upgrade | Use innodb_force_recovery to start, dump, reimport |
| Permissions/ownership | Error after restore or file move, file missing | chown -R mysql:mysql /var/lib/mysql, or reinitialize |
One last tip: before you upgrade, always mysqldump your databases. I've said this a hundred times, but it's the only way to make these problems a minor annoyance instead of a disaster.