Skip to content
Go back

Repair & Optimize all Mysql Databases one liner

· Updated:
By SumGuy 6 min read
Repair & Optimize all Mysql Databases one liner

Mysql tuner telling you to optimize your tables? or you just happen to be bored? Mysql optimize Reorganizes the physical storage of table data and associated index data, to reduce storage space and improve I/O efficiency when accessing the table. The exact changes made to each table depend on the storage engine used by that table. This statement does not work with views.  You should use OPTIMIZE TABLE in these cases, depending on the type of table:

This statement requires SELECT and INSERT privileges for the table.

well use this one liner to repair/optimize all your DBs in one go.

mysqlcheck --auto-repair --optimize --all-databases

voila!

But Wait, There’s More to Know Before You Nuke Your Tables

That one-liner is great, but there are a few things that’ll bite you if you’re not paying attention.

Authentication

By default, mysqlcheck will prompt for a password. If you’re running this as a cron job or just want to skip the prompt dance, you’ve got options:

Terminal window
# Pass credentials inline (works, but shows up in process list — not ideal)
mysqlcheck -u root -p'yourpassword' --auto-repair --optimize --all-databases
# Better: use a credentials file
mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize --all-databases

Set up /root/.my.cnf like this:

/root/.my.cnf
[client]
user=root
password=yourpassword

Then lock it down so you’re not just leaving credentials lying around:

Terminal window
chmod 600 /root/.my.cnf

Now your cron job can run it without a password prompt and without embedding credentials in the crontab itself. Worth the extra 30 seconds.

The InnoDB Elephant in the Room

Here’s the gotcha that’ll have you scratching your head: on InnoDB tables, OPTIMIZE TABLE doesn’t actually do what you think it does. MySQL just runs ALTER TABLE ... FORCE under the hood, which rebuilds the table. That works, but it acquires a full table lock for the duration. On a busy production server with a 10GB table, that’s a bad time.

If you’re running InnoDB and you can’t afford downtime, look into pt-online-schema-change from Percona Toolkit. But if this is a maintenance window situation or a dev/staging box, the one-liner is fine.

What the Output Actually Means

mysqlcheck is chatty. You’ll see a wall of output like:

Terminal window
mydb.users OK
mydb.orders Table is already up to date
mydb.sessions warning : Table does not support optimize, doing recreate + analyze instead
mydb.sessions status : OK

“Table does not support optimize” sounds alarming but it’s just MySQL telling you it’s InnoDB and it handled it differently. Not a problem.

What you do want to watch for:

Terminal window
mydb.broken_table error : Table './mydb/broken_table' is marked as crashed
mydb.broken_table repaired

That’s the --auto-repair flag doing its job. If you see “repaired” in the output, something was actually corrupt and got fixed — worth digging into why it crashed in the first place (usually an unclean shutdown).

Run It as a Cron Job

This is genuinely useful to run weekly during off-hours. Something like this in your crontab:

Terminal window
# Run every Sunday at 3am, log output
0 3 * * 0 mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize --all-databases >> /var/log/mysqlcheck.log 2>&1

Your 2 AM self will appreciate having a log to check instead of wondering if the thing even ran.

MariaDB Users

If you’re on MariaDB (and in 2024+ there’s a decent chance you are), the command is identical — mysqlcheck ships with MariaDB client tools and works exactly the same way. No adjustments needed.

Skipping Specific Databases (Because You Don’t Always Want Everything)

The --all-databases flag is convenient but sometimes too convenient. Maybe you’ve got a test database full of garbage you don’t care about, or a performance_schema that has no business being optimized. Running mysqlcheck on everything wastes time and occasionally causes confusion when MySQL tells you tables in information_schema can’t be optimized.

You can target specific databases instead:

Terminal window
# Just one database
mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize myapp_production
# Multiple specific databases — just list them
mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize myapp_production myapp_staging
# One specific table within a database
mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize myapp_production users

Or, if you want to stick with --all-databases but skip the system schemas, wrap it in a quick shell loop using the MySQL client to list only your app databases:

Terminal window
mysql --defaults-file=/root/.my.cnf -e "SHOW DATABASES;" \
| grep -vE "^(Database|information_schema|performance_schema|sys|mysql)$" \
| xargs -I{} mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize {}

This pulls the database list from MySQL directly, strips the system schemas with grep -v, then runs mysqlcheck against each one individually. A bit more verbose than the one-liner, but you get precise control without accidentally touching tables you shouldn’t.

One last thing: if you’re optimizing on a live system and want to see what’s happening in real time, mysqlcheck outputs as it goes — you can tee the output to a log file while still watching it scroll by:

Terminal window
mysqlcheck --defaults-file=/root/.my.cnf --auto-repair --optimize --all-databases \
| tee -a /var/log/mysqlcheck.log

That way you get the live view and a permanent record. Future you running grep repaired /var/log/mysqlcheck.log will owe present you a coffee.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Remove spaces or Edit chracters in filenames
Next Post
Restic vs Borg vs Kopia: Backup Tools for People Who've Lost Data Before

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts