229

I need to do a mysqldump of a database on a remote server, but the server does not have mysqldump installed. I would like to use the mysqldump on my machine to connect to the remote database and do the dump on my machine.

I have tried to create an ssh tunnel and then do the dump, but this does not seem to work. I tried:

ssh -f -L3310:remote.server:3306 user@remote.server -N

The tunnel is created with success. If I do

telnet localhost 3310

I get some blurb which shows the correct server mysql version. However, doing the following seems to try to connect locally

mysqldump -P 3310 -h localhost -u mysql_user -p database_name table_name
Brian Webster
  • 30,033
  • 48
  • 152
  • 225
Mauritz Hansen
  • 4,674
  • 3
  • 29
  • 34

4 Answers4

290

As I haven't seen it at serverfault yet, and the answer is quite simple:

Change:

ssh -f -L3310:remote.server:3306 user@remote.server -N

To:

ssh -f -L3310:localhost:3306 user@remote.server -N

And change:

mysqldump -P 3310 -h localhost -u mysql_user -p database_name table_name

To:

mysqldump -P 3310 -h 127.0.0.1 -u mysql_user -p database_name table_name

(do not use localhost, it's one of these 'special meaning' nonsense that probably connects by socket rather then by port)

edit: well, to elaborate: if host is set to localhost, a configured (or default) --socket option is assumed. See the manual for which option files are sought / used. Under Windows, this can be a named pipe.

Wrikken
  • 69,272
  • 8
  • 97
  • 136
197

One can invoke mysqldump locally against a remote server.

Example that worked for me:

mysqldump -h hostname-of-the-server -u mysql_user -p database_name > file.sql

I followed the mysqldump documentation on connection options.

Ondrej Burkert
  • 6,617
  • 2
  • 32
  • 27
  • 16
    No more need to open ssh tunnel before. +1 – Abhay Maurya Apr 30 '18 at 14:22
  • 1
    simplest aproach, theres no need to connect via ssh and bring the file back to your local machine! Just bring the dump directly! – TheGabiRod Jul 13 '18 at 17:26
  • 7
    this is dangerous, very dangerous. it requires that the port of mysql is open to public. which can be easily brute forced by bots. – louffi Sep 03 '18 at 14:47
  • 7
    How about being in a VPN? Or doing a dump from a machine you SSHed into that has access to the database machine? The port does not need to be public. – Ondrej Burkert Sep 05 '18 at 20:07
  • 13
    It's important to remember here that `-p` is for the password argument - not the database name. But it's insecure to store it in plain text so adding `-p` means you will be prompted for the password at login. Maybe it's just me but the `mysql` and thus the `mysql` dump syntax was never all that straight forward as far as command line arguments. – fIwJlxSzApHEZIl Sep 26 '18 at 16:55
  • There are situations where this is safe, this is useful for docker users, where the ports are exposed only to other containers in their network but not to the outside world. So it is not absolutely dangerous, it depends on the situation. – Jens Aug 05 '19 at 00:18
  • This response should be marked as correct. There is no need to have ssh credentials + database credentials. You only need interaction with REMOTE database, so you'll need to communicate only using Mysql database credentials. This command works properly if you have, of course, connection to remote server (you can just try it with ping). – eduardosufan Aug 08 '19 at 19:06
  • What if DB server is different from app server this will not work – Ameya May 25 '20 at 09:12
  • 1
    I do not follow what you mean @Ameya. There is a database server and we dump the data from it. I do not know what you mean by app server. – Ondrej Burkert May 26 '20 at 11:07
  • In a cloud or a production setup, the DB server is different from the application server, and the Bastian/Jump/Terminal server. Any way ignore my comment, looking for a solution which I am facing in this typical setup. Looking to automate DB backup before the installation of the new binary. – Ameya May 26 '20 at 14:50
  • 1
    Right. But then one can still reach the DB server (if it is actually reachable from the bastion/jump/.. server) but the intention of my answer was the simple cases :) – Ondrej Burkert May 27 '20 at 14:21
  • @volkovmqx Why it would be dangerous? Obviously database should be password protected, using port number as sole access control would be a clearly bad idea, I agree. – reducing activity Jun 29 '20 at 11:11
  • Will this solution require extra free space in the remote host to create the dump first? – Enrique Aug 19 '20 at 13:05
  • @volkovmqx Being dangerous really depends. You can brute force my sever all day long, but even if you guessed the password correctly, you wouldn't get in because I only granted privileges to 'myuser'@'[my IP]'. Now, if you granted to 'user'@'%' you'd be correct, but that's another discussion entirely. – user1119648 Oct 15 '20 at 02:48
  • This is the best answer in my opinion... If you add --single-transaction to the parameters, you will not get locks too, which can be nice for a dump of a live production database :) – MrG Jan 27 '21 at 14:27
  • 1
    If you cannot access MYSQL remotely, do `ssh root@ipaddress "mysqldump -u dbuser -p dbname | gzip -9" > dblocal.sql.gz` – FooBar Sep 29 '21 at 20:06
  • For people facing `Unknown table 'COLUMN_STATISTICS' in information_schema` you need to add `--column-statistics=0 `. Because this flag is enabled by default in Mysqldump 8 and can cause issues. The full command will look like `mysqldump --column-statistics=0 -h hostname-of-the-server -u mysql_user -p database_name > file.sql` – AbsarAkram Nov 02 '21 at 07:52
5

mysqldump from remote server use SSL

1- Security with SSL

192.168.0.101 - remote server

192.168.0.102 - local server

Remore server

CREATE USER 'backup_remote_2'@'192.168.0.102' IDENTIFIED WITH caching_sha2_password BY '3333333' REQUIRE SSL;

GRANT ALL PRIVILEGES ON *.* TO 'backup_remote_2'@'192.168.0.102';

FLUSH PRIVILEGES;

-

Local server

sudo /usr/local/mysql/bin/mysqldump \
 --databases test_1 \
 --host=192.168.0.101 \
 --user=backup_remote_2 \
 --password=3333333 \
 --master-data \
 --set-gtid-purged \
 --events \
 --triggers \
 --routines \
 --verbose \
 --ssl-mode=REQUIRED \
 --result-file=/home/db_1.sql

====================================

2 - Security with SSL (REQUIRE X509)

192.168.0.101 - remote server

192.168.0.102 - local server

Remore server

CREATE USER 'backup_remote'@'192.168.0.102' IDENTIFIED WITH caching_sha2_password BY '1111111' REQUIRE X509;

GRANT ALL PRIVILEGES ON *.* TO 'backup_remote'@'192.168.0.102';

FLUSH PRIVILEGES;

-

Local server

sudo /usr/local/mysql/bin/mysqldump \
 --databases test_1 \
 --host=192.168.0.101 \
 --user=backup_remote \
 --password=1111111 \
 --events \
 --triggers \
 --routines \
 --verbose \
 --ssl-mode=VERIFY_CA \
 --ssl-ca=/usr/local/mysql/data/ssl/ca.pem \
 --ssl-cert=/usr/local/mysql/data/ssl/client-cert.pem \
 --ssl-key=/usr/local/mysql/data/ssl/client-key.pem \
 --result-file=/home/db_name.sql

[Note]

On local server

/usr/local/mysql/data/ssl/

-rw------- 1 mysql mysql 1.7K Apr 16 22:28 ca-key.pem
-rw-r--r-- 1 mysql mysql 1.1K Apr 16 22:28 ca.pem
-rw-r--r-- 1 mysql mysql 1.1K Apr 16 22:28 client-cert.pem
-rw------- 1 mysql mysql 1.7K Apr 16 22:28 client-key.pem

Copy this files from remote server for (REQUIRE X509) or if SSL without (REQUIRE X509) do not copy


On remote server

/usr/local/mysql/data/

-rw------- 1 mysql mysql 1.7K Apr 16 22:28  ca-key.pem
-rw-r--r-- 1 mysql mysql 1.1K Apr 16 22:28  ca.pem
-rw-r--r-- 1 mysql mysql 1.1K Apr 16 22:28  client-cert.pem
-rw------- 1 mysql mysql 1.7K Apr 16 22:28  client-key.pem
-rw------- 1 mysql mysql 1.7K Apr 16 22:28  private_key.pem
-rw-r--r-- 1 mysql mysql  451 Apr 16 22:28  public_key.pem
-rw-r--r-- 1 mysql mysql 1.1K Apr 16 22:28  server-cert.pem
-rw------- 1 mysql mysql 1.7K Apr 16 22:28  server-key.pem

my.cnf

[mysqld]
# SSL
ssl_ca=/usr/local/mysql/data/ca.pem
ssl_cert=/usr/local/mysql/data/server-cert.pem
ssl_key=/usr/local/mysql/data/server-key.pem

Increase Password Security

https://dev.mysql.com/doc/refman/8.0/en/password-security-user.html

0

Bassed on this page here:

Compare two MySQL databases

I modified it so you can use ddbb in diferent hosts.


#!/bin/sh

echo "Usage: dbdiff [user1:pass1@dbname1:host] [user2:pass2@dbname2:host] [ignore_table1:ignore_table2...]"

dump () {
  up=${1%%@*}; down=${1##*@}; user=${up%%:*}; pass=${up##*:}; dbname=${down%%:*}; host=${down##*:};
  mysqldump --opt --compact --skip-extended-insert -u $user -p$pass $dbname -h $host $table > $2
}

rm -f /tmp/db.diff

# Compare
up=${1%%@*}; down=${1##*@}; user=${up%%:*}; pass=${up##*:}; dbname=${down%%:*}; host=${down##*:};
for table in `mysql -u $user -p$pass $dbname -h $host -N -e "show tables" --batch`; do
  if [ "`echo $3 | grep $table`" = "" ]; then
    echo "Comparing '$table'..."
    dump $1 /tmp/file1.sql
    dump $2 /tmp/file2.sql
    diff -up /tmp/file1.sql /tmp/file2.sql >> /tmp/db.diff
  else
    echo "Ignored '$table'..."
  fi
done
less /tmp/db.diff
rm -f /tmp/file1.sql /tmp/file2.sql