MySQL Point-in-Time Recovery (PITR): Complete Guide (2025)
Point-in-time recovery (PITR) allows you to restore a MySQL database to any specific moment, not just your last backup. If a disaster occurs at 3:47 PM and your last backup was at midnight, PITR can recover your database to 3:46 PM - losing only one minute of data instead of nearly 16 hours.
This capability is essential for minimizing data loss in production environments. Without PITR, you're limited to restoring your most recent backup, potentially losing hours or even a full day of transactions.
This guide explains how point-in-time recovery works in MySQL, the components required to implement it, and practical steps for recovering your database to a specific moment.
Understanding Recovery Point Objective (RPO)
Recovery Point Objective (RPO) defines the maximum acceptable amount of data loss measured in time. If your RPO is 1 hour, you can tolerate losing up to 1 hour of data during a disaster. If your RPO is 15 minutes, you need backup systems that capture changes at least every 15 minutes.
RPO vs RTO
Don't confuse RPO with RTO (Recovery Time Objective). RTO is how long it takes to restore service after a failure. RPO is how much data you might lose. You might have an RTO of 2 hours (acceptable downtime) but an RPO of 15 minutes (maximum data loss).
| Backup Strategy | Typical RPO | Data Loss Scenario |
|---|---|---|
| Daily backups only | 24 hours | Crash at 5 PM loses entire day's work |
| Hourly backups | 1 hour | Crash at 3:45 PM loses 45 minutes |
| Daily backup + binary logs | Minutes | Crash at 3:45 PM loses only uncommitted transactions |
| 15-minute incremental + logs | 15 minutes | Crash at 3:45 PM loses maximum 15 minutes |
Your actual RPO depends on both your backup frequency AND whether you have binary logs enabled. Without binary logs, you can only restore to your last backup point.
How MySQL Binary Logs Enable PITR
MySQL binary logs (binlogs) record every data modification in your database - INSERT, UPDATE, DELETE, and DDL statements. These logs are the foundation of point-in-time recovery.
Binary Log Basics
When binary logging is enabled, MySQL writes every change to sequential log files (mysql-bin.000001, mysql-bin.000002, etc.). Each entry includes the exact timestamp and position, allowing you to replay changes up to any specific moment.
-- Check if binary logging is enabled
SHOW VARIABLES LIKE 'log_bin';
-- View current binary log files
SHOW BINARY LOGS;
-- See binary log events
SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 10;Enabling Binary Logs
Binary logging is configured in your MySQL configuration file (my.cnf or my.ini):
[mysqld]
log_bin = /var/log/mysql/mysql-bin
server_id = 1
binlog_format = ROW
expire_logs_days = 14
max_binlog_size = 100MUse ROW format for binary logs. It records actual data changes rather than SQL statements, making recovery more reliable and avoiding issues with non-deterministic functions.
The PITR Recovery Process
Point-in-time recovery is a two-step process: first restore your base backup, then replay binary logs up to your target time.
Step 1: Restore Base Backup
Start by restoring your most recent full backup that occurred BEFORE your target recovery time. For physical backups, this means copying files back. For logical backups, this means importing the SQL dump.
# For physical backup (Mariabackup)
mariabackup --copy-back --target-dir=/backup/full
chown -R mysql:mysql /var/lib/mysql
# For logical backup (mysqldump)
mysql -u root -p < backup.sqlStep 2: Replay Binary Logs
After restoring the base backup, use mysqlbinlog to replay binary logs from the backup's position to your target recovery time.
# Replay binary logs up to specific time
mysqlbinlog --stop-datetime="2025-01-15 15:46:00" \
/var/log/mysql/mysql-bin.000042 \
/var/log/mysql/mysql-bin.000043 \
| mysql -u root -p
# Or stop at specific position
mysqlbinlog --stop-position=12345 \
/var/log/mysql/mysql-bin.000043 \
| mysql -u root -pIdentifying the Recovery Point
To recover to a specific point, you need to know what happened when. Use mysqlbinlog to examine log contents:
# View events around a specific time
mysqlbinlog --start-datetime="2025-01-15 15:40:00" \
--stop-datetime="2025-01-15 15:50:00" \
/var/log/mysql/mysql-bin.000043 | less
# Look for the problematic statement (e.g., DROP TABLE, DELETE)
# Note the position BEFORE that statement Common PITR Scenarios
Scenario 1: Accidental Data Deletion
A developer runs DELETE FROM orders WHERE status = 'pending' without a WHERE clause at 2:30 PM, deleting all orders. Your last backup was at midnight.
- Restore midnight backup to a recovery server (not production)
- Use mysqlbinlog to find the exact position of the DELETE statement
- Replay binary logs from midnight to just before the DELETE
- Export the recovered orders table
- Import into production or use INSERT...SELECT to restore data
Scenario 2: Database Corruption
Your production server experiences storage failure at 4:15 PM, corrupting the database. Last backup was at midnight.
- Stop MySQL and preserve binary logs (copy to safe location)
- Restore midnight backup
- Replay binary logs from midnight to 4:14 PM (just before corruption)
- Verify data integrity
- Resume production
Scenario 3: Ransomware Attack
Malware encrypts your database at 11:20 AM. You detect it at 11:45 AM.
- Isolate affected systems
- Restore from backup prior to infection (ideally off-site backup)
- Replay binary logs up to 11:19 AM (before encryption began)
- Verify no malicious changes exist in the recovered data
- Implement additional security before resuming production
Binary Log Management Best Practices
Binary logs are essential for PITR but require careful management. They grow continuously and can fill your disk if not maintained.
Retention Policy
Keep binary logs long enough to cover your backup retention plus recovery time. If you keep 7 days of backups, retain at least 8-10 days of binary logs.
-- MySQL 8.0+
SET GLOBAL binlog_expire_logs_seconds = 864000; -- 10 days
-- MySQL 5.7 and earlier
SET GLOBAL expire_logs_days = 10;Binary Log Backup
Binary logs must be backed up separately from your database backups. If binary logs are lost, you cannot perform point-in-time recovery beyond your last full backup.
- Copy binary logs to remote storage immediately after rotation
- Keep binary logs on different storage than your database
- Verify binary log backups are readable and complete
- Monitor binary log disk usage and set alerts
Monitoring Binary Log Health
-- Check binary log status
SHOW MASTER STATUS;
-- Check disk usage
SHOW BINARY LOGS;
-- Verify binary log writing is active
SHOW VARIABLES LIKE 'log_bin'; PITR with Physical Backups
Physical backup tools like Mariabackup and XtraBackup record the binary log position at backup time, making PITR integration seamless.
Capturing Binary Log Position
After preparing a physical backup, the binary log coordinates are stored in xtrabackup_binlog_info:
# After mariabackup --prepare
cat /backup/full/xtrabackup_binlog_info
# Output: mysql-bin.000042 12345Complete PITR with Mariabackup
# 1. Restore physical backup
systemctl stop mariadb
rm -rf /var/lib/mysql/*
mariabackup --copy-back --target-dir=/backup/full
chown -R mysql:mysql /var/lib/mysql
systemctl start mariadb
# 2. Get binary log position from backup
cat /backup/full/xtrabackup_binlog_info
# Shows: mysql-bin.000042 12345
# 3. Replay binary logs from that position to target time
mysqlbinlog --start-position=12345 \
--stop-datetime="2025-01-15 15:46:00" \
/var/log/mysql/mysql-bin.000042 \
/var/log/mysql/mysql-bin.000043 \
| mysql -u root -p How DBCalm Simplifies PITR
DBCalm automates point-in-time recovery by combining 15-minute incremental backups with simplified recovery workflows.
15-Minute Recovery Points
With incremental backups every 15 minutes, DBCalm ensures your maximum data loss is 15 minutes - without requiring manual binary log management. Each backup captures a consistent state that can be restored directly.
Simplified Recovery
- Select any 15-minute recovery point from the dashboard
- No manual binary log identification or replay required
- Automated backup preparation and verification
- Restore to original location or separate recovery server
This approach eliminates the complexity of traditional PITR while maintaining tight recovery point objectives. You get the benefits of point-in-time recovery without managing binary logs separately.
Frequently Asked Questions
Do I need binary logs if I have frequent backups?
It depends on your RPO requirements. If you have 15-minute incremental backups, your maximum data loss is already 15 minutes without binary logs. Binary logs allow recovery to the exact second but add complexity.
For most applications, 15-minute recovery points are sufficient. Critical financial systems or high-transaction environments might benefit from combining frequent backups with binary log PITR for sub-minute recovery capability.
How much disk space do binary logs require?
Binary log size depends on your write activity. A database processing 1000 transactions per hour might generate 10-50 MB of binary logs per hour. High-activity databases can generate gigabytes daily.
Monitor your binary log growth for a week to establish baselines, then plan storage accordingly. Set expire_logs_days or binlog_expire_logs_seconds to automatically purge old logs.
Can I do PITR with mysqldump backups?
Yes, but you need to use the --master-data or --source-data option when creating the dump. This records the binary log position in the dump file.
After importing the dump, replay binary logs from that position. However, for large databases, the slow restore time of mysqldump makes physical backups a better choice for PITR scenarios.
Related Guides
Ready to Implement Better Backups?
Questions? Contact our team to discuss your backup needs.