Configure MySQL backup monitoring with Prometheus alerts and Grafana dashboards

Intermediate 45 min May 31, 2026 78 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up automated monitoring for MySQL backups with Prometheus metrics collection, alerting rules for backup failures, and comprehensive Grafana dashboards for backup status visualization.

Prerequisites

  • MySQL 8.0 or later installed
  • Root or sudo access
  • At least 4GB RAM
  • 10GB free disk space

What this solves

Database backup monitoring ensures your MySQL backups run successfully and alerts you immediately when they fail. This tutorial sets up automated monitoring using Prometheus to collect backup metrics, configures alerting rules for backup failures, and creates Grafana dashboards for visual tracking of backup status, timing, and storage usage.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions of all components.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install MySQL backup tools

Install mysqldump and Percona XtraBackup for creating reliable MySQL backups with consistent snapshots.

sudo apt install -y mysql-client-core-8.0 curl gnupg2
wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
sudo apt update
sudo apt install -y percona-xtrabackup-80
sudo dnf install -y mysql curl
sudo dnf install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
sudo percona-release enable-only tools release
sudo dnf install -y percona-xtrabackup-80

Create MySQL backup user

Create a dedicated MySQL user with minimal privileges required for backup operations.

mysql -u root -p
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'SecureBackupPassword123!';
GRANT SELECT, LOCK TABLES, SHOW VIEW, PROCESS, REPLICATION CLIENT ON . TO 'backup_user'@'localhost';
GRANT RELOAD ON . TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Create backup directory structure

Set up organized directories for storing backups and monitoring scripts with proper permissions.

sudo mkdir -p /var/backups/mysql/{daily,weekly,monthly}
sudo mkdir -p /opt/backup-monitoring
sudo chown mysql:mysql /var/backups/mysql
sudo chmod 750 /var/backups/mysql

Create backup monitoring script

Create a script that performs backups while collecting metrics for Prometheus monitoring.

#!/bin/bash

METRICS_FILE="/var/lib/node_exporter/textfile_collector/mysql_backup.prom"
BACKUP_DIR="/var/backups/mysql/daily"
LOG_FILE="/var/log/mysql-backup.log"
DB_USER="backup_user"
DB_PASS="SecureBackupPassword123!"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="mysql_backup_${DATE}.sql.gz"

Initialize metrics

echo "# HELP mysql_backup_duration_seconds Time taken for MySQL backup in seconds" > $METRICS_FILE echo "# TYPE mysql_backup_duration_seconds gauge" >> $METRICS_FILE echo "# HELP mysql_backup_size_bytes Size of MySQL backup file in bytes" >> $METRICS_FILE echo "# TYPE mysql_backup_size_bytes gauge" >> $METRICS_FILE echo "# HELP mysql_backup_success Backup success status (1=success, 0=failure)" >> $METRICS_FILE echo "# TYPE mysql_backup_success gauge" >> $METRICS_FILE echo "# HELP mysql_backup_timestamp_seconds Timestamp of last backup" >> $METRICS_FILE echo "# TYPE mysql_backup_timestamp_seconds gauge" >> $METRICS_FILE

Start backup process

START_TIME=$(date +%s) echo "$(date): Starting MySQL backup" >> $LOG_FILE

Perform backup

if mysqldump -u $DB_USER -p$DB_PASS --single-transaction --routines --triggers --all-databases | gzip > "${BACKUP_DIR}/${BACKUP_NAME}"; then END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) BACKUP_SIZE=$(stat -c%s "${BACKUP_DIR}/${BACKUP_NAME}") echo "$(date): Backup completed successfully. Size: ${BACKUP_SIZE} bytes, Duration: ${DURATION}s" >> $LOG_FILE # Update metrics echo "mysql_backup_duration_seconds $DURATION" >> $METRICS_FILE echo "mysql_backup_size_bytes $BACKUP_SIZE" >> $METRICS_FILE echo "mysql_backup_success 1" >> $METRICS_FILE echo "mysql_backup_timestamp_seconds $END_TIME" >> $METRICS_FILE # Cleanup old backups (keep 7 days) find $BACKUP_DIR -name "mysql_backup_*.sql.gz" -mtime +7 -delete exit 0 else END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) echo "$(date): Backup failed" >> $LOG_FILE # Update failure metrics echo "mysql_backup_duration_seconds $DURATION" >> $METRICS_FILE echo "mysql_backup_size_bytes 0" >> $METRICS_FILE echo "mysql_backup_success 0" >> $METRICS_FILE echo "mysql_backup_timestamp_seconds $END_TIME" >> $METRICS_FILE exit 1 fi
sudo chmod +x /opt/backup-monitoring/mysql-backup-monitor.sh
sudo chown mysql:mysql /opt/backup-monitoring/mysql-backup-monitor.sh

Install and configure Node Exporter

Install Node Exporter to collect system metrics and expose the backup metrics to Prometheus.

cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xvfz node_exporter-1.8.2.linux-amd64.tar.gz
sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo mkdir -p /var/lib/node_exporter/textfile_collector
sudo chown node_exporter:node_exporter /var/lib/node_exporter/textfile_collector

Create Node Exporter systemd service

Configure Node Exporter as a systemd service with textfile collector enabled for backup metrics.

[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter --collector.textfile.directory=/var/lib/node_exporter/textfile_collector
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
sudo systemctl status node_exporter

Install and configure Prometheus

Install Prometheus to scrape metrics from Node Exporter and monitor backup status.

sudo apt install -y prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.54.1/prometheus-2.54.1.linux-amd64.tar.gz
tar xvfz prometheus-2.54.1.linux-amd64.tar.gz
sudo cp prometheus-2.54.1.linux-amd64/{prometheus,promtool} /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus

Configure Prometheus scraping

Configure Prometheus to scrape Node Exporter metrics including the MySQL backup metrics.

global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "/etc/prometheus/mysql_backup_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - localhost:9093

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']
    scrape_interval: 30s
    metrics_path: /metrics

Create MySQL backup alerting rules

Define Prometheus alerting rules to detect backup failures and long-running backups.

groups:
  - name: mysql_backup_alerts
    rules:
      - alert: MySQLBackupFailed
        expr: mysql_backup_success == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "MySQL backup failed"
          description: "MySQL backup has failed. Last backup status: {{ $value }}"

      - alert: MySQLBackupTooOld
        expr: (time() - mysql_backup_timestamp_seconds) > 86400
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "MySQL backup is too old"
          description: "MySQL backup is older than 24 hours. Last backup was {{ $value | humanizeDuration }} ago."

      - alert: MySQLBackupTooLong
        expr: mysql_backup_duration_seconds > 3600
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "MySQL backup taking too long"
          description: "MySQL backup took {{ $value | humanizeDuration }} to complete, which is longer than expected."

      - alert: MySQLBackupSizeUnusual
        expr: mysql_backup_size_bytes < (mysql_backup_size_bytes offset 1d) * 0.5 and mysql_backup_size_bytes > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "MySQL backup size significantly smaller than previous day"
          description: "Current backup size is {{ $value | humanizeBytes }}, which is less than 50% of yesterday's backup size."
sudo chown prometheus:prometheus /etc/prometheus/mysql_backup_rules.yml

Install and configure Alertmanager

Install Alertmanager to handle alert notifications from Prometheus rules.

sudo apt install -y prometheus-alertmanager
cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar xvfz alertmanager-0.27.0.linux-amd64.tar.gz
sudo cp alertmanager-0.27.0.linux-amd64/{alertmanager,amtool} /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false alertmanager
sudo mkdir -p /etc/alertmanager /var/lib/alertmanager
sudo chown alertmanager:alertmanager /etc/alertmanager /var/lib/alertmanager

Configure Alertmanager notifications

Set up Alertmanager to send email notifications for backup alerts. For more advanced notifications, check out our Alertmanager webhook integration tutorial.

global:
  smtp_smarthost: 'localhost:587'
  smtp_from: 'alerts@example.com'
  smtp_auth_username: 'alerts@example.com'
  smtp_auth_password: 'your_smtp_password'

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'mysql-backup-team'

receivers:
  - name: 'mysql-backup-team'
    email_configs:
      - to: 'dba-team@example.com'
        subject: 'MySQL Backup Alert: {{ .GroupLabels.alertname }}'
        body: |
          {{ range .Alerts }}
          Alert: {{ .Annotations.summary }}
          Description: {{ .Annotations.description }}
          Severity: {{ .Labels.severity }}
          Time: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
          {{ end }}
sudo chown alertmanager:alertmanager /etc/alertmanager/alertmanager.yml

Start Prometheus and Alertmanager

Enable and start both Prometheus and Alertmanager services.

sudo systemctl enable --now prometheus
sudo systemctl enable --now alertmanager
sudo systemctl status prometheus
sudo systemctl status alertmanager

Install and configure Grafana

Install Grafana for creating visual dashboards to monitor backup metrics and trends.

sudo apt install -y software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo tee /etc/yum.repos.d/grafana.repo <

Configure Grafana data source

Add Prometheus as a data source in Grafana and start the service.

sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server
Note: Access Grafana at http://your-server-ip:3000 with default credentials admin/admin. Change the password on first login.

Create backup monitoring dashboard

Create a comprehensive Grafana dashboard for MySQL backup monitoring. Navigate to Grafana, add Prometheus as a data source (http://localhost:9090), then import this dashboard configuration.

{
  "dashboard": {
    "id": null,
    "title": "MySQL Backup Monitoring",
    "tags": ["mysql", "backup", "monitoring"],
    "timezone": "browser",
    "panels": [
      {
        "id": 1,
        "title": "Backup Success Rate (24h)",
        "type": "stat",
        "targets": [{
          "expr": "mysql_backup_success",
          "legendFormat": "Success"
        }],
        "fieldConfig": {
          "defaults": {
            "thresholds": {
              "steps": [
                {"color": "red", "value": 0},
                {"color": "green", "value": 1}
              ]
            }
          }
        },
        "gridPos": {"h": 8, "w": 6, "x": 0, "y": 0}
      },
      {
        "id": 2,
        "title": "Last Backup Size",
        "type": "stat",
        "targets": [{
          "expr": "mysql_backup_size_bytes",
          "legendFormat": "Size"
        }],
        "fieldConfig": {
          "defaults": {
            "unit": "bytes"
          }
        },
        "gridPos": {"h": 8, "w": 6, "x": 6, "y": 0}
      },
      {
        "id": 3,
        "title": "Backup Duration",
        "type": "stat",
        "targets": [{
          "expr": "mysql_backup_duration_seconds",
          "legendFormat": "Duration"
        }],
        "fieldConfig": {
          "defaults": {
            "unit": "s"
          }
        },
        "gridPos": {"h": 8, "w": 6, "x": 12, "y": 0}
      },
      {
        "id": 4,
        "title": "Time Since Last Backup",
        "type": "stat",
        "targets": [{
          "expr": "time() - mysql_backup_timestamp_seconds",
          "legendFormat": "Age"
        }],
        "fieldConfig": {
          "defaults": {
            "unit": "s"
          }
        },
        "gridPos": {"h": 8, "w": 6, "x": 18, "y": 0}
      },
      {
        "id": 5,
        "title": "Backup Size Trend (7 days)",
        "type": "graph",
        "targets": [{
          "expr": "mysql_backup_size_bytes",
          "legendFormat": "Backup Size"
        }],
        "yAxes": [{
          "unit": "bytes"
        }],
        "gridPos": {"h": 8, "w": 12, "x": 0, "y": 8}
      },
      {
        "id": 6,
        "title": "Backup Duration Trend (7 days)",
        "type": "graph",
        "targets": [{
          "expr": "mysql_backup_duration_seconds",
          "legendFormat": "Duration"
        }],
        "yAxes": [{
          "unit": "s"
        }],
        "gridPos": {"h": 8, "w": 12, "x": 12, "y": 8}
      }
    ],
    "time": {
      "from": "now-7d",
      "to": "now"
    },
    "refresh": "30s"
  }
}

Schedule backup automation

Set up a cron job to run backups daily and ensure consistent monitoring data collection.

sudo crontab -u mysql -e
# Run MySQL backup daily at 2 AM
0 2   * /opt/backup-monitoring/mysql-backup-monitor.sh >> /var/log/mysql-backup.log 2>&1

Run weekly backup on Sundays at 1 AM

0 1 0 /opt/backup-monitoring/mysql-backup-monitor.sh >> /var/log/mysql-backup.log 2>&1

Configure firewall access

Open required ports

Configure firewall rules to allow access to monitoring services.

sudo ufw allow 9090/tcp comment 'Prometheus'
sudo ufw allow 9093/tcp comment 'Alertmanager'
sudo ufw allow 3000/tcp comment 'Grafana'
sudo ufw allow 9100/tcp comment 'Node Exporter'
sudo ufw reload

Verify your setup

Test the complete backup monitoring pipeline to ensure all components work together correctly.

# Test backup script manually
sudo -u mysql /opt/backup-monitoring/mysql-backup-monitor.sh

Check metrics file

cat /var/lib/node_exporter/textfile_collector/mysql_backup.prom

Verify Prometheus is scraping metrics

curl http://localhost:9090/api/v1/query?query=mysql_backup_success

Check service statuses

sudo systemctl status prometheus sudo systemctl status alertmanager sudo systemctl status grafana-server sudo systemctl status node_exporter

View backup logs

tail -f /var/log/mysql-backup.log

Access your monitoring services:

  • Prometheus: http://your-server-ip:9090
  • Alertmanager: http://your-server-ip:9093
  • Grafana: http://your-server-ip:3000

Common issues

SymptomCauseFix
Backup script fails with permission deniedIncorrect file ownership or permissionssudo chown mysql:mysql /opt/backup-monitoring/mysql-backup-monitor.sh && sudo chmod +x /opt/backup-monitoring/mysql-backup-monitor.sh
Metrics not appearing in PrometheusNode Exporter not configured with textfile collectorCheck Node Exporter service: sudo systemctl restart node_exporter
Alerts not triggeringAlertmanager not connected to PrometheusVerify /etc/prometheus/prometheus.yml alertmanagers configuration
Grafana shows no dataPrometheus data source not configuredAdd Prometheus data source: http://localhost:9090
Backup user authentication failsMySQL user privileges insufficientRe-run MySQL user creation commands with proper grants
Large backup files consume disk spaceNo cleanup policy configuredBackup script includes cleanup: find $BACKUP_DIR -name "mysql_backup_*.sql.gz" -mtime +7 -delete

Next steps

Running this in production?

Want this handled for you? Setting up backup monitoring once is straightforward. Keeping it patched, monitored, backed up and tuned across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.