MySQL binary logs: how to delete them and limit how long they are kept
MySQL and MariaDB write every change to the data into the binary log. That is a useful thing: it drives
replication, and together with a full backup it lets you restore to any point in time. It is also the reason
a server that has been running for two years suddenly has no disk space left, with a directory full of
mysql-bin.000001, mysql-bin.000002 and so on.
Two jobs, in this order: delete what you no longer need, then stop the pile from growing back.
Look before you delete
SHOW BINARY LOGS;
SHOW VARIABLES LIKE 'log_bin%';
The first statement lists the log files with their size, the second shows whether logging is on and where the files live. If you run replicas, check how far they have read before you remove anything — purging a log a replica still needs breaks replication, and the fix is a new copy of the data.
Delete the old logs
Purge by date, or up to a specific file:
PURGE BINARY LOGS BEFORE '2026-11-01 00:00:00';
PURGE BINARY LOGS TO 'mysql-bin.000123';
A rolling window of seven days, without typing a date:
PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 7 DAY);
And everything up to this moment, which leaves only the log the server is writing right now:
PURGE BINARY LOGS BEFORE NOW();
The statement needs the BINLOG_ADMIN privilege in MySQL 8 (SUPER in older versions, BINLOG ADMIN in
MariaDB). It deletes the files and updates the index file — which is exactly why rm mysql-bin.* is the
wrong tool. After an rm the index still lists files that no longer exist, and the server complains about it
on every start.
Stop them from piling up again
The server can expire old logs on its own. Which variable you need depends on the product:
MySQL 8.0 and newer uses seconds. The default is 2592000, thirty days.
SET PERSIST binlog_expire_logs_seconds = 604800; -- 7 days, survives a restart
MariaDB uses days:
SET GLOBAL expire_logs_days = 7;
SET GLOBAL applies immediately but is forgotten on restart — MySQL 8 has SET PERSIST for that, MariaDB
needs the configuration file. Put the setting in the [mysqld] section of /etc/mysql/my.cnf or
/etc/my.cnf:
[mysqld]
# MySQL 8 and newer
binlog_expire_logs_seconds = 604800
# MariaDB
expire_logs_days = 7
Use the line that fits your server; an unknown variable stops MySQL from starting. expire_logs_days has
been deprecated in MySQL 8.0 and is gone in MySQL 8.4, while MariaDB still accepts it. When in doubt, ask the
server:
SHOW VARIABLES LIKE '%expire_logs%';
While you are in the file, max_binlog_size (default 1 GB) decides how large a single log file grows before
the server rotates to the next one. Smaller files are purged in finer steps.
Switching the log off completely
If there is no replica and no point-in-time recovery plan, you can stop writing binary logs at all:
[mysqld]
skip-log-bin
Be clear about what you give up: after that, a backup from last night is the newest state you can restore. On any server that holds customer data, limiting the lifetime is the better trade than switching the log off.
Frequently asked questions
Can I just delete the mysql-bin files with rm?
No. The server keeps an index file that lists the binary logs. If you remove files behind its back, the index still points at them and the server logs errors; replication can stop. Use PURGE BINARY LOGS, which deletes the files and updates the index.
Do I need binary logs on a single server without replication?
Only for point-in-time recovery: a full backup plus the binary logs lets you roll forward to the minute before a mistake. Without that plan the logs are just disk usage, and you can switch them off with skip-log-bin.
How long should I keep them?
At least as long as the oldest backup you would actually restore, plus a margin for the slowest replica. Seven days is a common choice for a single server with daily backups.
Which variable does my server use?
Run SHOW VARIABLES LIKE "%expire_logs%". MySQL 8 reports binlog_expire_logs_seconds, MariaDB reports expire_logs_days, and newer MariaDB versions report both.