Moving a website, restoring a backup or cloning a staging environment all come down to the same two operations: dumping a database to a file and loading it back. On a VPS Linux Infrawire you can do both in a few commands, without any web interface. This guide covers consistent dumps, compression, large files, character encoding and direct server-to-server transfer.
📋 Prerequisites
- A Linux VPS running Ubuntu 24.04 or Debian 12 with root SSH access (the IP and the root password are available in your customer area)
- MySQL or MariaDB installed, or at least the client (
apt install mariadb-client) - A database user with
SELECT,SHOW VIEW,TRIGGER,LOCK TABLESandEVENTprivileges on the database to dump - Enough free disk space: check with
df -h
1. Export a database with mysqldump
For InnoDB tables (the default engine), --single-transaction produces a consistent snapshot without locking the tables, so your site keeps running during the dump.
Bashmysqldump -u USER -p --single-transaction --quick DBNAME > DBNAME.sql
On recent MariaDB releases the tool is also available as mariadb-dump; the options are identical.
2. Include routines, triggers and events
Triggers are dumped by default, but stored procedures, functions and scheduled events must be requested explicitly. Forcing the character set avoids surprises with accents and emojis.
Bashmysqldump -u USER -p --single-transaction --routines --triggers --events \ --default-character-set=utf8mb4 DBNAME > DBNAME.sql
Useful variants:
Bash# Structure only, no rows mysqldump -u USER -p --no-data DBNAME > schema.sql # Several databases, with CREATE DATABASE statements mysqldump -u USER -p --single-transaction --databases DB1 DB2 > two-dbs.sql # Every database on the server mysqldump -u root -p --single-transaction --routines --events --all-databases > all.sql
3. Compress the dump with gzip
SQL text compresses very well. Pipe the output straight into gzip so the uncompressed file never touches the disk.
Bashmysqldump -u USER -p --single-transaction --routines --events DBNAME | gzip > DBNAME_$(date +%F).sql.gz
To avoid typing the password (and keeping it out of ps output), store it in ~/.my.cnf:
INI[client] user=USER password=YOUR_PASSWORD
Bashchmod 600 ~/.my.cnf
4. Import a dump
Create the target database first, with a modern character set, then load the file.
Bashmysql -u USER -p -e 'CREATE DATABASE IF NOT EXISTS DBNAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' mysql -u USER -p --default-character-set=utf8mb4 DBNAME < DBNAME.sql # From a compressed file gunzip -c DBNAME.sql.gz | mysql -u USER -p --default-character-set=utf8mb4 DBNAME
Warning: by default the dump contains DROP TABLE IF EXISTS, so importing into an existing database replaces the tables of the same name. Back up the destination first.
5. Handle large files
For multi-gigabyte dumps, run the import inside tmux so an SSH disconnection does not interrupt it, and use pv to see the progress.
Bashapt install -y tmux pv tmux new -s import pv DBNAME.sql.gz | gunzip | mysql -u USER -p --max-allowed-packet=512M DBNAME
Detach with Ctrl+B then D, and reattach later with tmux attach -t import.
6. Transfer directly to another server over SSH
No intermediate file is needed: the dump travels through an encrypted SSH pipe and is loaded on arrival. Credentials are read from ~/.my.cnf (or the local socket as root) on each side.
Bashmysqldump --single-transaction --routines --events DBNAME | gzip \ | ssh root@NEW_VPS_IP 'gunzip | mysql DBNAME'
The database DBNAME must already exist on the destination server.
✅ Verify the result
Bashgzip -t DBNAME.sql.gz && echo 'archive OK' mysql -e 'SHOW TABLES;' DBNAME mysql -e 'SELECT COUNT(*) FROM TABLENAME;' DBNAME mysql -e "SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name='DBNAME';"
Compare row counts of a few key tables between source and destination.
🔧 Troubleshooting
ERROR 1045 Access denied : wrong user or password, or the user is not allowed from this host. Test with mysql -u USER -p first.
ERROR 2006 MySQL server has gone away : a row or query exceeds max_allowed_packet. Raise it on the server in the [mysqld] section of the configuration and restart the service, or pass --max-allowed-packet=512M to the client.
Garbled accents after import : the file was read with the wrong charset. Dump with --default-character-set=utf8mb4 and import with the same option.
ERROR 1227 or DEFINER errors : the dump references a user that does not exist on the destination. Strip the clause while importing:
Bashsed -E 's/DEFINER=`[^`]+`@`[^`]+`//g' DBNAME.sql | mysql -u USER -p DBNAME
🎉 Your databases are now easy to back up, restore and migrate between servers!