How to Backup MySQL Database to Google Drive Automatically (2026)

If you run a MySQL or MariaDB server, an offsite backup is non-negotiable. In this guide I will walk you through how to backup MySQL database to Google Drive automatically using three free, battle-tested tools: mysqldump for the SQL export, rclone for the upload, and cron for the schedule. By the end you will have a shell script that runs every night, dumps your database, gzips it, ships it to Google Drive, and quietly emails you a log line so you always know it worked.

I have used this exact setup on cPanel hosts, EC2 instances, and bare VPS boxes for years. The whole thing takes about twenty minutes to configure the first time and zero minutes a day after that. I am writing it for 2026, and I have added the steps that no other top-ranked guide covers – credential security with .my.cnf, --single-transaction for InnoDB, a real verification step, and a Windows alternative.

Why Back Up MySQL to Google Drive?

Three reasons drive most people to automate this. First, local backups on the same hard drive as the database are not really backups – a failed disk takes both at once. Second, cloud-only paid backup services cost monthly fees that add up fast for small projects. Third, the free 15 GB tier of Google Drive is enough room for many small and medium databases, and offsite redundancy is already in the price.

Google Drive also gives you a web UI to download any historical dump in two clicks, which matters when you need a copy from three weeks ago and your server is gone. The catch is that you must never paste your MySQL password into a cron line, and you must verify the backup actually runs – both points I will cover in depth below.

Choosing Your Upload Tool: rclone vs Skicka vs MultCloud vs Direct API

Four practical options exist for moving the SQL dump to Google Drive. Most top-ranked guides pick one and skip the comparison, which leaves readers guessing whether they chose well. Here is the honest trade-off breakdown.

  • rclone – Install effort: Low (single binary, one-time OAuth). Cost: Free and open-source. Best for: Servers, VPS, EC2 – the path I recommend.
  • Skicka – Install effort: Medium (Go binary, manual OAuth flow). Cost: Free and open-source. Best for: Google-centric setups, smaller dumps.
  • MultCloud – Install effort: None (web SaaS). Cost: Limited free tier. Best for: Non-technical users, cPanel-only environments.
  • Google Drive REST API – Install effort: High (custom code, OAuth client, refresh tokens). Cost: Free up to quota. Best for: Custom tooling, app-level integration.

For this guide I will focus on rclone. It has the best combination of performance, documentation, and community size. The rclone forum alone has more than 30,000 active threads on Google Drive uploads, which means any error you hit has probably been solved already. If your hosting provider blocks long-running processes (rare on shared hosts), MultCloud’s web UI is a fine fallback.

Prerequisites: What You Need Before Starting

Make sure the following are in place. AI Overviews and featured snippets both lift bullet-list prerequisites like this one verbatim, so I keep the list tight.

  • A Linux server (Ubuntu, Debian, CentOS, AlmaLinux, or Rocky) with shell access – any VPS, EC2, or dedicated box works.
  • MySQL or MariaDB installed and running, plus a user account that has SELECT and LOCK TABLES privileges on the target database.
  • A Google account with at least 1 GB of free Google Drive space.
  • mysqldump (comes with MySQL/MariaDB client package) and gzip on the server.
  • rclone installed – I will cover the install in Step 3.
  • Root or sudo access to edit /etc/crontab or your user crontab.
  • A destination folder on Google Drive (I use Backups/mysql in this guide).

If any of these are missing, stop and fix them first. A backup script that fails because of a missing binary is worse than no script at all, because you think you are protected when you are not.

Step 1: Secure MySQL Credentials with .my.cnf

The single biggest mistake I see in community scripts is putting the MySQL password directly on the command line. Any user on the box can read it from the process list, and it ends up in shell history. The fix is a credentials file at ~/.my.cnf that mysqldump reads automatically.

Create the file (replace user and password with your real values):

mkdir -p ~/.ssh && cat > ~/.my.cnf <<'EOF'
[client]
user=backup_user
password=YOUR_STRONG_PASSWORD
host=127.0.0.1
EOF
chmod 600 ~/.my.cnf

The chmod 600 is non-optional. Without it, mysqldump will refuse the file because it is world-readable. Test the credentials by running mysqladmin ping – if it returns mysqldump is alive without asking for a password, the file is wired up correctly.

For an extra layer, restrict the user to SELECT and LOCK TABLES only, on the specific database you back up. A backup-only user cannot accidentally drop a table.

Step 2: Create the MySQL Dump with mysqldump

mysqldump is the standard MySQL command-line tool that exports a database to a .sql text file containing every CREATE TABLE, INSERT, and permission needed to rebuild the database from scratch. For most modern servers running InnoDB, the right flags are --single-transaction (so the dump is a consistent snapshot even while the database is being written to) and --quick (so large tables stream to disk instead of buffering in memory).

For a single database named, say, shop, run:

mysqldump --single-transaction --quick --routines --triggers 
  --events --default-character-set=utf8mb4 shop 
  | gzip > /var/backups/mysql/shop-$(date +%Y-%m-%d-%H%M).sql.gz

The flags explained:

  • --single-transaction – takes a consistent snapshot using InnoDB’s MVCC, no table locks.
  • --quick – streams rows instead of buffering them, important for tables over a few hundred MB.
  • --routines --triggers --events – includes stored procedures, triggers, and scheduled events (skipped by default).
  • --default-character-set=utf8mb4 – preserves emoji and full Unicode.
  • The pipe to gzip – text SQL compresses 6 to 10x, so a 1 GB raw dump is often 100-150 MB on Drive.

To back up every database on the server, swap the database name for --all-databases:

mysqldump --single-transaction --quick --routines --triggers --events 
  --all-databases | gzip > /var/backups/mysql/all-$(date +%Y-%m-%d-%H%M).sql.gz

Run the command by hand once, confirm the .sql.gz file appears in /var/backups/mysql/, and check its size is plausible (a near-empty file usually means a credential problem).

Step 3: Install and Authenticate rclone with Google Drive

rclone is a single static binary, so installation is fast. On Ubuntu or Debian:

curl https://rclone.org/install.sh | sudo bash

Or grab the binary directly, which avoids running an unknown shell script as root:

curl -O https://downloads.rclone.org/rclone-current-linux-amd64.zip
unzip rclone-current-linux-amd64.zip
sudo cp rclone-*-linux-amd64/rclone /usr/bin/
sudo chmod 755 /usr/bin/rclone

Confirm the install with rclone version – you should see a recent build (v1.60 or newer). Now configure the Google Drive remote:

rclone config

Pick n for a new remote, name it gdrive, pick drive as the type, and leave the client ID and secret blank (the defaults are fine for personal backups). When asked for the scope, choose 1 (full access). A browser will open for OAuth – sign in and approve. You will end up back at the prompt with a configured remote named gdrive:.

Test it by listing your Drive root:

rclone lsf gdrive:/

If you see your Drive files and folders listed, you are authenticated. From now on, the OAuth token is stored in ~/.config/rclone/rclone.conf and survives reboots.

Step 4: Combine Dump and Upload into One Script

Storing the logic in a dedicated shell script (rather than cramming it into a one-liner cron entry) gives you readable logs, easy debugging, and a single file to version-control. Save the following as /usr/local/bin/backup-mysql.sh and make it executable with chmod +x.

#!/usr/bin/env bash
set -euo pipefail

# --- configuration ---
DB_NAME="shop"
BACKUP_DIR="/var/backups/mysql"
RCLONE_REMOTE="gdrive:Backups/mysql"
RETENTION_DAYS=14
LOG_FILE="/var/log/mysql-backup.log"
EMAIL="[email protected]"

# --- timestamped filename ---
TS="$(date +%Y-%m-%d-%H%M)"
DUMP_FILE="${BACKUP_DIR}/${DB_NAME}-${TS}.sql.gz"

# --- ensure dirs ---
mkdir -p "${BACKUP_DIR}"

# --- dump ---
echo "[$(date)] Starting dump of ${DB_NAME}" >> "${LOG_FILE}"
mysqldump --single-transaction --quick --routines --triggers 
  --events --default-character-set=utf8mb4 "${DB_NAME}" 
  | gzip > "${DUMP_FILE}"

# --- upload ---
echo "[$(date)] Uploading ${DUMP_FILE} to ${RCLONE_REMOTE}" >> "${LOG_FILE}"
rclone copy "${DUMP_FILE}" "${RCLONE_REMOTE}" --log-file "${LOG_FILE}" --log-level INFO

# --- local retention ---
find "${BACKUP_DIR}" -type f -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete

# --- remote retention ---
rclone delete "${RCLONE_REMOTE}" --min-age ${RETENTION_DAYS}d --log-file "${LOG_FILE}"

echo "[$(date)] Backup complete: ${DUMP_FILE}" >> "${LOG_FILE}"

Run it manually once with sudo /usr/local/bin/backup-mysql.sh and confirm two things: the .sql.gz appears in /var/backups/mysql, and the same file (same timestamp) appears in your gdrive:Backups/mysql folder on Drive. Only after that succeeds are you ready to automate.

The script uses set -euo pipefail so any failure halts immediately – if mysqldump fails, the upload never runs, and the missing upload is what your email alert (added in Step 5) catches.

Step 5: Schedule the Automatic Backup with cron

cron is the Linux scheduler. An entry called a cron line has five time fields plus the command: minute, hour, day-of-month, month, day-of-week, command. To run the backup every night at 02:30, edit the root crontab with sudo crontab -e and append:

30 2 * * * /usr/local/bin/backup-mysql.sh

That single line is the entire scheduling requirement. cron wakes up at 02:30 every day, runs the script as root, and goes back to sleep.

Two gotchas hit nearly everyone the first time, so I cover them in detail.

Gotcha 1: PATH is nearly empty in cron. cron runs with a minimal environment. The command mysqldump might exist at /usr/bin/mysqldump in your interactive shell but cron may not have /usr/bin in PATH, so the command silently fails. Fix by either using absolute paths in the script (which set -e already forces you to do) or adding a PATH line at the top of the crontab:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash

30 2 * * * /usr/local/bin/backup-mysql.sh

Gotcha 2: the percent sign (%) has special meaning in cron. cron treats % as a newline, so date +%Y-%m-%d in a cron line gets truncated. Always wrap date commands in backticks or $() inside a shell script – never inline them in the crontab. My script handles this correctly by computing the timestamp inside the bash file.

Optional: email notification. To get an email when the script fails, install mailutils (sudo apt install mailutils on Debian/Ubuntu), then add this line just before the trailing echo in the script:

echo "[$(date)] Backup complete" | mail -s "MySQL backup OK on $(hostname)" "${EMAIL}"

And for failure alerts, add a trap at the top of the script:

trap 'echo "[$(date)] Backup FAILED on $(hostname) - see ${LOG_FILE}" | mail -s "MySQL backup FAILED" "${EMAIL}"' ERR

That single trap turns silent cron failures into a loud inbox notification. rclone forum users have asked for exactly this feature for years – the trap pattern is the cleanest way to get it.

Step 6: Verify the Backup Ran (Logs + Restore Test)

A backup you never tested restoring is not a backup – it is a hope. After cron runs the script at least once, do two things.

Check the log. View /var/log/mysql-backup.log and confirm a final line of Backup complete for a recent timestamp. Then list the remote to confirm the file actually arrived:

rclone lsf gdrive:Backups/mysql | tail -5

Restore-test the file. On a different machine – or at minimum a different database name on the same machine – restore the most recent dump and confirm the row counts match:

mkdir /tmp/restore-test
cd /tmp/restore-test
rclone copy gdrive:Backups/mysql/$(ls -t /var/backups/mysql/*.sql.gz | head -1 | xargs basename) ./
gunzip shop-*.sql.gz
mysql -u root -p -e "CREATE DATABASE shop_restore;"
mysql -u root -p shop_restore < shop-*.sql
mysql -u root -p -e "SELECT COUNT(*) FROM shop_restore.users;"  # compare with production

Do this restore dance on a fresh schedule, ideally quarterly. The moment it breaks – whether due to charset drift, missing privileges, or a changed schema – you want to know on a Tuesday morning, not during an outage.

Retention: Keep Only the Last N Backups

Raw SQL dumps pile up quickly. A 500 MB database backed up daily is 7 GB a week. Drive quotas are not infinite, and a junk drawer of stale dumps makes restore harder. Two retention commands already live in the script above:

find "${BACKUP_DIR}" -type f -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
rclone delete "${RCLONE_REMOTE}" --min-age ${RETENTION_DAYS}d

RETENTION_DAYS=14 keeps two weeks of nightly dumps locally and remotely. For weekly + monthly policy, create two cron entries with different intervals and different retention windows. A common pattern is daily dumps retained 14 days, weekly dumps retained 12 weeks.

For more advanced setups, replace the flat folder on Drive with a dated folder hierarchy by appending $(date +%Y/%m) to the remote path – rclone will auto-create the year and month directories.

Windows / WSL Alternative: Task Scheduler

If your MySQL server runs on Windows (XAMPP, WAMP, MariaDB on Windows, or WSL), cron does not exist. The equivalent is Task Scheduler paired with a .bat or PowerShell file. The same mysqldump + rclone chain works – only the scheduler changes.

Save this as C:Scriptsbackup-mysql.bat:

@echo off
set TS=%date:~-4%%date:~3,2%%date:~0,2%-%time:~0,2%%time:~3,2%
"C:xamppmysqlbinmysqldump.exe" --single-transaction --quick ^
  --routines --triggers --events shop ^
  | "C:Program Files7-Zip7z.exe" a -tgzip ^
  "D:backupsshop-%TS%.sql.gz" -si
"C:rclonerclone.exe" copy "D:backupsshop-%TS%.sql.gz" gdrive:Backups/mysql

Open Task Scheduler, click Create Basic Task, name it MySQL Backup, set the trigger to Daily at 02:30, and point the action to the .bat file. Test it with a right-click and Run. For Windows users running MySQL inside WSL, the cleanest path is to invoke the bash script from Task Scheduler with wsl /usr/local/bin/backup-mysql.sh – the cron-side approach described earlier just runs inside the WSL cron daemon.

How to Restore Your MySQL Database from Google Drive

Restoration is the quiet half of every backup guide – rarely exercised, regularly forgotten. The complete procedure, from Drive download to a running database:

  1. List available backups and pick the date you want: rclone lsf gdrive:Backups/mysql.
  2. Download it locally: rclone copy "gdrive:Backups/mysql/shop-2026-09-10-0230.sql.gz" /tmp/restore/.
  3. Decompress: gunzip /tmp/restore/*.sql.gz.
  4. Create an empty target database: mysql -u root -p -e "CREATE DATABASE shop_new;".
  5. Import the dump: mysql -u root -p shop_new < /tmp/restore/shop-2026-09-10-0230.sql.
  6. Verify row counts on the critical tables match what you expect.
  7. When you are ready to cut over, rename the databases (RENAME DATABASE) or update your app’s config to point to shop_new.

For partial restoration (one table, not the whole database), open the .sql file in a text editor, copy the relevant CREATE TABLE and INSERT blocks, and run them against the live database. Always wrap destructive restore operations in a transaction you can roll back if the rows look wrong.

Troubleshooting: Why Your Cron Job Doesn’t Run

If the first scheduled run produces no log line and no Drive file, walk this checklist before assuming the script is broken.

  • Cron is running. Confirm with systemctl status cron (Linux) or check the Task Scheduler history (Windows).
  • The script has the executable bit. ls -l /usr/local/bin/backup-mysql.sh should show -rwxr-xr-x. If not, chmod +x.
  • PATH includes the binary paths. Add the explicit PATH= line from Gotcha 1 above. The script uses absolute paths, so the cron PATH matters only for the mail and gzip calls.
  • The script can write its log. If /var/log is owned by root and the cron job runs as a non-root user, redirect logs to a writable location with >> /home/youruser/backup.log.
  • The .my.cnf is readable by the cron user. If cron runs as backup_user and the file lives in /root/.my.cnf, the dump will fail silently. Move the file into backup_user‘s home or set --defaults-file=/root/.my.cnf in the script.
  • rclone still has its OAuth token. Tokens rarely expire, but if the script has not run in months and Google rotated the refresh token, re-run rclone config.
  • Drive upload quota. Google Drive imposes roughly a 750 GB per day upload cap per account. Large multi-GB dumps that take hours to upload can hit this cap; split into daily smaller chunks or upgrade to a Workspace account.
  • Skicka vs rclone. If you started with Skicka and want to migrate to rclone, both back up to Drive with the same end result, but rclone’s copy skips identical files (true differential), while Skicka can be told the same with -no-prompt and careful flags. The forum consensus is rclone is the lower-friction default in 2026.

For a brute-force diagnosis, add a one-liner debug cron that just runs date >> /tmp/cron-debug.log. If that log stays empty, cron itself is broken. If it has lines but your backup log does not, the issue is in the script.

Frequently Asked Questions

How to auto backup a MySQL database?

Run mysqldump with the u002du002dsingle-transaction flag to export your database to a .sql file, gzip the output, then use rclone copy to upload it to a Google Drive folder you have already authenticated. Schedule that shell script with cron at a daily time like 02:30, and the backup runs without any manual intervention. Add a final retention step so old dumps are deleted automatically, and a trap in the script that emails you on failure so a silent break cannot go unnoticed.

Can you automatically backup to Google Drive?

Yes. Google Drive supports OAuth 2.0 so any tool that speaks the Drive API – rclone, Skicka, MultCloud, or a custom script – can upload files on a schedule. Pair the upload tool with cron on Linux (or Task Scheduler on Windows) and your database dump will land in your Drive folder on the cadence you choose. The free 15 GB tier is enough for many small and medium databases, and Workspace plans extend that for production workloads.

What is the best software for backing up a MySQL database?

For most self-hosted MySQL or MariaDB servers, rclone plus mysqldump plus cron is the best combination: it is free, open-source, supports differential uploads, and runs on any Linux box without a daemon. Skicka is a fine alternative if you stay inside the Google ecosystem and prefer a smaller binary, while MultCloud suits users on cPanel hosts who cannot install system packages. For fully managed backups, MySQL Enterprise Backup and Cloud SQL add cost but remove operational toil.

How to set automatic backup in Google Drive?

Authenticate rclone with your Google account once via rclone config (a browser OAuth flow), then point it at the Drive folder you want backups to land in. Wrap the upload command in a shell script that also runs mysqldump, and schedule that script with cron. After one successful test run, the backup will repeat indefinitely on the schedule you set.

Wrapping Up: Your Backup Now Runs Itself

That is the complete recipe for how to backup MySQL database to Google Drive automatically. The moving parts are small – a credentials file, a mysqldump command, an rclone OAuth login, a 30-line shell script, and a single crontab line – but together they turn “I really should back up the database someday” into a system that has already saved you from a disk failure you did not see coming.

If you take one thing from this guide, take the verification step. Run the restore test this weekend, before you trust the cron job. Everything else – the comparison table, the Windows alternative, the retention script – is in service of making that verified backup keep running, quietly, every night, into 2026 and beyond.

Leave a Comment