Regular backups already capture binlog position automatically when PITR is enabled at the MySQL level. No special flag needed.
404 lines
10 KiB
Markdown
404 lines
10 KiB
Markdown
# MySQL/MariaDB Point-in-Time Recovery (PITR)
|
|
|
|
This guide explains how to use dbbackup for Point-in-Time Recovery with MySQL and MariaDB databases.
|
|
|
|
## Overview
|
|
|
|
Point-in-Time Recovery (PITR) allows you to restore your database to any specific moment in time, not just to when a backup was taken. This is essential for:
|
|
|
|
- Recovering from accidental data deletion or corruption
|
|
- Restoring to a state just before a problematic change
|
|
- Meeting regulatory compliance requirements for data recovery
|
|
|
|
### How MySQL PITR Works
|
|
|
|
MySQL PITR uses binary logs (binlogs) which record all changes to the database:
|
|
|
|
1. **Base Backup**: A full database backup with the binlog position recorded
|
|
2. **Binary Log Archiving**: Continuous archiving of binlog files
|
|
3. **Recovery**: Restore base backup, then replay binlogs up to the target time
|
|
|
|
```
|
|
┌─────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
│ Base Backup │ --> │ binlog.00001 │ --> │ binlog.00002 │ --> │ binlog.00003 │
|
|
│ (pos: 1234) │ │ │ │ │ │ (current) │
|
|
└─────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
|
|
│ │ │ │
|
|
▼ ▼ ▼ ▼
|
|
10:00 AM 10:30 AM 11:00 AM 11:30 AM
|
|
↑
|
|
Target: 11:15 AM
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
### MySQL Configuration
|
|
|
|
Binary logging must be enabled in MySQL. Add to `my.cnf`:
|
|
|
|
```ini
|
|
[mysqld]
|
|
# Enable binary logging
|
|
log_bin = mysql-bin
|
|
server_id = 1
|
|
|
|
# Recommended: Use ROW format for PITR
|
|
binlog_format = ROW
|
|
|
|
# Optional but recommended: Enable GTID for easier replication and recovery
|
|
gtid_mode = ON
|
|
enforce_gtid_consistency = ON
|
|
|
|
# Keep binlogs for at least 7 days (adjust as needed)
|
|
expire_logs_days = 7
|
|
# Or for MySQL 8.0+:
|
|
# binlog_expire_logs_seconds = 604800
|
|
```
|
|
|
|
After changing configuration, restart MySQL:
|
|
```bash
|
|
sudo systemctl restart mysql
|
|
```
|
|
|
|
### MariaDB Configuration
|
|
|
|
MariaDB configuration is similar:
|
|
|
|
```ini
|
|
[mysqld]
|
|
log_bin = mariadb-bin
|
|
server_id = 1
|
|
binlog_format = ROW
|
|
|
|
# MariaDB uses different GTID implementation (auto-enabled with log_slave_updates)
|
|
log_slave_updates = ON
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### 1. Check PITR Status
|
|
|
|
```bash
|
|
# Check if MySQL is properly configured for PITR
|
|
dbbackup pitr mysql-status
|
|
```
|
|
|
|
Example output:
|
|
```
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
MySQL/MariaDB PITR Status (mysql)
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
PITR Status: ❌ NOT CONFIGURED
|
|
Binary Logging: ✅ ENABLED
|
|
Binlog Format: ROW
|
|
GTID Mode: ON
|
|
Current Position: mysql-bin.000042:1234
|
|
|
|
PITR Requirements:
|
|
✅ Binary logging enabled
|
|
✅ Row-based logging (recommended)
|
|
```
|
|
|
|
### 2. Enable PITR
|
|
|
|
```bash
|
|
# Enable PITR and configure archive directory
|
|
dbbackup pitr mysql-enable --archive-dir /backups/binlog_archive
|
|
```
|
|
|
|
### 3. Create a Base Backup
|
|
|
|
```bash
|
|
# Create a backup - binlog position is automatically recorded
|
|
dbbackup backup single mydb
|
|
```
|
|
|
|
> **Note:** All backups automatically capture the current binlog position when PITR is enabled at the MySQL level. This position is stored in the backup metadata and used as the starting point for binlog replay during recovery.
|
|
|
|
### 4. Start Binlog Archiving
|
|
|
|
```bash
|
|
# Run binlog archiver in the background
|
|
dbbackup binlog watch --binlog-dir /var/lib/mysql --archive-dir /backups/binlog_archive --interval 30s
|
|
```
|
|
|
|
Or set up a cron job for periodic archiving:
|
|
```bash
|
|
# Archive new binlogs every 5 minutes
|
|
*/5 * * * * dbbackup binlog archive --binlog-dir /var/lib/mysql --archive-dir /backups/binlog_archive
|
|
```
|
|
|
|
### 5. Restore to Point in Time
|
|
|
|
```bash
|
|
# Restore to a specific time
|
|
dbbackup restore pitr mydb_backup.sql.gz --target-time '2024-01-15 14:30:00'
|
|
```
|
|
|
|
## Commands Reference
|
|
|
|
### PITR Commands
|
|
|
|
#### `pitr mysql-status`
|
|
Show MySQL/MariaDB PITR configuration and status.
|
|
|
|
```bash
|
|
dbbackup pitr mysql-status
|
|
```
|
|
|
|
#### `pitr mysql-enable`
|
|
Enable PITR for MySQL/MariaDB.
|
|
|
|
```bash
|
|
dbbackup pitr mysql-enable \
|
|
--archive-dir /backups/binlog_archive \
|
|
--retention-days 7 \
|
|
--require-row-format \
|
|
--require-gtid
|
|
```
|
|
|
|
Options:
|
|
- `--archive-dir`: Directory to store archived binlogs (required)
|
|
- `--retention-days`: Days to keep archived binlogs (default: 7)
|
|
- `--require-row-format`: Require ROW binlog format (default: true)
|
|
- `--require-gtid`: Require GTID mode enabled (default: false)
|
|
|
|
### Binlog Commands
|
|
|
|
#### `binlog list`
|
|
List available binary log files.
|
|
|
|
```bash
|
|
# List binlogs from MySQL data directory
|
|
dbbackup binlog list --binlog-dir /var/lib/mysql
|
|
|
|
# List archived binlogs
|
|
dbbackup binlog list --archive-dir /backups/binlog_archive
|
|
```
|
|
|
|
#### `binlog archive`
|
|
Archive binary log files.
|
|
|
|
```bash
|
|
dbbackup binlog archive \
|
|
--binlog-dir /var/lib/mysql \
|
|
--archive-dir /backups/binlog_archive \
|
|
--compress
|
|
```
|
|
|
|
Options:
|
|
- `--binlog-dir`: MySQL binary log directory
|
|
- `--archive-dir`: Destination for archived binlogs (required)
|
|
- `--compress`: Compress archived binlogs with gzip
|
|
- `--encrypt`: Encrypt archived binlogs
|
|
- `--encryption-key-file`: Path to encryption key file
|
|
|
|
#### `binlog watch`
|
|
Continuously monitor and archive new binlog files.
|
|
|
|
```bash
|
|
dbbackup binlog watch \
|
|
--binlog-dir /var/lib/mysql \
|
|
--archive-dir /backups/binlog_archive \
|
|
--interval 30s \
|
|
--compress
|
|
```
|
|
|
|
Options:
|
|
- `--interval`: How often to check for new binlogs (default: 30s)
|
|
|
|
#### `binlog validate`
|
|
Validate binlog chain integrity.
|
|
|
|
```bash
|
|
dbbackup binlog validate --binlog-dir /var/lib/mysql
|
|
```
|
|
|
|
Output shows:
|
|
- Whether the chain is complete (no missing files)
|
|
- Any gaps in the sequence
|
|
- Server ID changes (indicating possible failover)
|
|
- Total size and file count
|
|
|
|
#### `binlog position`
|
|
Show current binary log position.
|
|
|
|
```bash
|
|
dbbackup binlog position
|
|
```
|
|
|
|
Output:
|
|
```
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
Current Binary Log Position
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
File: mysql-bin.000042
|
|
Position: 123456
|
|
GTID Set: 3E11FA47-71CA-11E1-9E33-C80AA9429562:1-1000
|
|
|
|
Position String: mysql-bin.000042:123456
|
|
```
|
|
|
|
## Restore Scenarios
|
|
|
|
### Restore to Specific Time
|
|
|
|
```bash
|
|
# Restore to January 15, 2024 at 2:30 PM
|
|
dbbackup restore pitr mydb_backup.sql.gz \
|
|
--target-time '2024-01-15 14:30:00'
|
|
```
|
|
|
|
### Restore to Specific Position
|
|
|
|
```bash
|
|
# Restore to a specific binlog position
|
|
dbbackup restore pitr mydb_backup.sql.gz \
|
|
--target-position 'mysql-bin.000042:12345'
|
|
```
|
|
|
|
### Dry Run (Preview)
|
|
|
|
```bash
|
|
# See what SQL would be replayed without applying
|
|
dbbackup restore pitr mydb_backup.sql.gz \
|
|
--target-time '2024-01-15 14:30:00' \
|
|
--dry-run
|
|
```
|
|
|
|
### Restore to Backup Point Only
|
|
|
|
```bash
|
|
# Restore just the base backup without replaying binlogs
|
|
dbbackup restore pitr mydb_backup.sql.gz --immediate
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Archiving Strategy
|
|
|
|
- Archive binlogs frequently (every 5-30 minutes)
|
|
- Use compression to save disk space
|
|
- Store archives on separate storage from the database
|
|
|
|
### 2. Retention Policy
|
|
|
|
- Keep archives for at least as long as your oldest valid base backup
|
|
- Consider regulatory requirements for data retention
|
|
- Use the cleanup command to purge old archives:
|
|
|
|
```bash
|
|
dbbackup binlog cleanup --archive-dir /backups/binlog_archive --retention-days 30
|
|
```
|
|
|
|
### 3. Validation
|
|
|
|
- Regularly validate your binlog chain:
|
|
```bash
|
|
dbbackup binlog validate --binlog-dir /var/lib/mysql
|
|
```
|
|
|
|
- Test restoration periodically on a test environment
|
|
|
|
### 4. Monitoring
|
|
|
|
- Monitor the `dbbackup binlog watch` process
|
|
- Set up alerts for:
|
|
- Binlog archiver failures
|
|
- Gaps in binlog chain
|
|
- Low disk space on archive directory
|
|
|
|
### 5. GTID Mode
|
|
|
|
Enable GTID for:
|
|
- Easier tracking of replication position
|
|
- Automatic failover in replication setups
|
|
- Simpler point-in-time recovery
|
|
|
|
## Troubleshooting
|
|
|
|
### Binary Logging Not Enabled
|
|
|
|
**Error**: "Binary logging appears to be disabled"
|
|
|
|
**Solution**: Add to my.cnf and restart MySQL:
|
|
```ini
|
|
[mysqld]
|
|
log_bin = mysql-bin
|
|
server_id = 1
|
|
```
|
|
|
|
### Missing Binlog Files
|
|
|
|
**Error**: "Gaps detected in binlog chain"
|
|
|
|
**Causes**:
|
|
- `RESET MASTER` was executed
|
|
- `expire_logs_days` is too short
|
|
- Binlogs were manually deleted
|
|
|
|
**Solution**:
|
|
- Take a new base backup immediately
|
|
- Adjust retention settings to prevent future gaps
|
|
|
|
### Permission Denied
|
|
|
|
**Error**: "Failed to read binlog directory"
|
|
|
|
**Solution**:
|
|
```bash
|
|
# Add dbbackup user to mysql group
|
|
sudo usermod -aG mysql dbbackup_user
|
|
|
|
# Or set appropriate permissions
|
|
sudo chmod g+r /var/lib/mysql/mysql-bin.*
|
|
```
|
|
|
|
### Wrong Binlog Format
|
|
|
|
**Warning**: "binlog_format = STATEMENT (ROW recommended)"
|
|
|
|
**Impact**: STATEMENT format may not capture all changes accurately
|
|
|
|
**Solution**: Change to ROW format (requires restart):
|
|
```ini
|
|
[mysqld]
|
|
binlog_format = ROW
|
|
```
|
|
|
|
### Server ID Changes
|
|
|
|
**Warning**: "server_id changed from X to Y (possible master failover)"
|
|
|
|
This warning indicates the binlog chain contains events from different servers, which may happen during:
|
|
- Failover in a replication setup
|
|
- Restoring from a different server's backup
|
|
|
|
This is usually informational but review your topology if unexpected.
|
|
|
|
## MariaDB-Specific Notes
|
|
|
|
### GTID Format
|
|
|
|
MariaDB uses a different GTID format than MySQL:
|
|
- **MySQL**: `3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5`
|
|
- **MariaDB**: `0-1-100` (domain-server_id-sequence)
|
|
|
|
### Tool Detection
|
|
|
|
dbbackup automatically detects MariaDB and uses:
|
|
- `mariadb-binlog` if available (MariaDB 10.4+)
|
|
- Falls back to `mysqlbinlog` for older versions
|
|
|
|
### Encrypted Binlogs
|
|
|
|
MariaDB supports binlog encryption. If enabled, ensure the key is available during archive and restore operations.
|
|
|
|
## See Also
|
|
|
|
- [PITR.md](PITR.md) - PostgreSQL PITR documentation
|
|
- [DOCKER.md](DOCKER.md) - Running in Docker environments
|
|
- [CLOUD.md](CLOUD.md) - Cloud storage for archives
|