Database migration is the process of migrating data from one or more source databases to one or more target databases by using a database migration service. When a migration is finished, the dataset in the source databases resides fully, though possibly restructured, in the target databases.
References
Prerequisites
- Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. Download Docker
- MySQL is the most popular open source database. Download MySQL
- PostgreSQL is the world’s most advanced open source relational database. Download PostgreSQL
Build pgloader from sources
Fix the issue is to build pgloader from sources.
To take advantage of pgLoader’s useSSL option, a feature that allows for migrations from MySQL over an SSL connection. This feature is only available in versions 3.5.1 and newer of pgLoader.
Before installing pgLoader, you will need to install its dependencies.
sbcl
: A Common Lisp compiler
unzip
: A de-archiver for .zip files
libsqlite3-dev
: A collection of development files for SQLite 3
gawk
: Short for “GNU awk”, a pattern scanning and processing language
curl
: A command line tool for transferring data from a URL
make
: A utility for managing package compilation
freetds-dev
: A client library for MS SQL and Sybase databases
libzip-dev
: A library for reading, creating, and modifying zip archives
pgloader
: A tool to load data into PostgreSQL
1
2
3
4
5
6
7
8
|
docker exec -it postgresql bash
apt update
apt upgrade
apt install sbcl unzip libsqlite3-dev gawk curl make freetds-dev libzip-dev
# apt install pgloader
# apt install ca-certificates
|
Check the latest pgLoader Release
1
2
3
4
5
6
7
8
9
10
11
12
|
# Transfer the tarball
postgres-server$ curl -fsSLO https://github.com/dimitri/pgloader/archive/v3.6.9.tar.gz
# Extract the tarball
postgres-server$ tar xvf v3.6.9.tar.gz
# Navigate into the new pgLoader parent directory
postgres-server$ cd pgloader-3.6.9/
# Then use the make utility to compile the pgloader binary:
postgres-server$ make pgloader
# Move the binary file into the /usr/local/bin directory where executable files are
postgres-server$ mv ./build/bin/pgloader /usr/local/bin/
# Test that pgLoader was installed correctly by checking its version
postgres-server$ pgloader --version
|
mysql-ssl-docker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
docker exec -it mysql bash
mysql -u root -p \
--ssl-ca=/etc/certs/root-ca.pem \
--ssl-cert=/etc/certs/client-cert.pem \
--ssl-key=/etc/certs/client-key.pem
Enter password: secret
docker run --rm -it --network migration_wpnet -v `pwd`/conf/certs:/etc/certs \
imega/mysql-client \
mysql -h mysql -u root -p \
--ssl-ca=/etc/certs/root-ca.pem \
--ssl-cert=/etc/certs/client-cert.pem \
--ssl-key=/etc/certs/client-key.pem
Enter password: secret
mysql> show global variables like '%ssl%';
mysql> show global variables like '%secure%';
mysql> status
mysql> show databases;
mysql> show grants for usermysql@'%';
# usermysqlssl without password
mysql> CREATE USER 'usermysqlssl'@'%' REQUIRE SSL;
mysql> GRANT ALL PRIVILEGES ON `dbmysql`.* TO 'usermysqlssl'@'%';
mysql> exit
docker run --rm -it --network migration_wpnet -v `pwd`/conf/certs:/etc/certs \
imega/mysql-client \
mysql -h mysql -u usermysqlssl \
--ssl-ca=/etc/certs/root-ca.pem \
--ssl-cert=/etc/certs/client-cert.pem \
--ssl-key=/etc/certs/client-key.pem \
dbmysql
# usermysqlssl with password
mysql> CREATE USER 'usermysqlssl'@'%' IDENTIFIED BY 'pwdmysqlssl' REQUIRE SSL;
mysql> GRANT ALL ON `dbmysql`.* TO 'usermysqlssl'@'%';
mysql> FLUSH PRIVILEGES;
mysql> exit
docker run --rm -it --network migration_wpnet -v `pwd`/conf/certs:/etc/certs \
imega/mysql-client \
mysql -h mysql -u usermysqlssl -p \
--ssl-ca=/etc/certs/root-ca.pem \
--ssl-cert=/etc/certs/client-cert.pem \
--ssl-key=/etc/certs/client-key.pem \
dbmysql
Enter password: pwdmysqlssl
|
postgresql-docker
useSSL=false
2023-01-15T21:00:11.194000Z ERROR mysql: Failed to connect to mysql at "mysql" (port 3306) as user "usermysql": Condition QMYND:MYSQL-UNSUPPORTED-AUTHENTICATION was signalled.
useSSL=true
2023-01-15T21:00:39.164000Z ERROR mysql: Failed to connect to mysql at "mysql" (port 3306) as user "usermysql": SSL verify error: 19 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
If you try to migrate your MySQL database using SSL the attempt would fail.
The reason for this is that pgLoader isn’t able to read MySQL’s configuration files, and thus doesn’t know where to look for the CA certificate or client certificate that you copied to your PostgreSQL server in the prerequisite SSL/TLS configuration guide. Rather than ignoring SSL requirements, though, pgLoader requires the use of trusted certificates in cases where SSL is needed to connect to MySQL. Accordingly, you can resolve this issue by adding the ca.pem and client-cert.pem files to trusted certificate store.
To do this, copy over the ca.pem
and client-cert.pem
files to the /usr/local/share/ca-certificates/
directory. Note that you must also rename these files so they have the .crt
file extension. If you don’t rename them, your system will not be able to recognize that you’ve added these new certificates:
1
2
3
|
cp /usr/local/share/ca-certificates/root-ca.pem /usr/local/share/ca-certificates/ca.pem.crt
cp /usr/local/share/ca-certificates/client-cert.pem /usr/local/share/ca-certificates/client-cert.pem.crt
update-ca-certificates
|
To connect mysql
from postgres
:
1
2
3
4
5
6
7
8
|
docker exec -it postgresql bash
apt install default-mysql-client
mysql -h mysql -u usermysqlssl -p \
--ssl-ca=/usr/local/share/ca-certificates/root-ca.pem \
--ssl-cert=/usr/local/share/ca-certificates/client-cert.pem \
--ssl-key=/usr/local/share/ca-certificates/client-key.pem \
dbmysql
Enter password: pwdmysqlssl
|
To create username, password and table for postgres
:
1
2
3
4
5
6
7
8
|
apt install sudo
sudo -u postgres createuser --interactive -P
Enter name of role to add: pgloader_pg
Enter password for new role: postgresql_password
Enter it again: postgresql_password
Shall the new role be a superuser? (y/n) y
sudo -u postgres createdb new_db
|
1
|
pgloader mysql://usermysqlssl:pwdmysqlssl@mysql/dbmysql?useSSL=true postgresql://postgres:postgres@localhost/new_db
|
To test it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# First, connect to PostgreSQL using the psql tool. Second, enter the password for the user postgres and press the Enter keyboard:
$ psql -U postgres -W
# Third, switch to a database e.g.., dbmysql:
postgres=# \c dbmysql
# Note that you can connect to a specific database when you log in to the PostgreSQL database server:
$ psql -U pgloader_pg -d new_db
new_db=# \dt
# Use the \dt command from the PostgreSQL command prompt to show tables in the dbmysql database:
new_db=# \dt+
# to show databases : \l
# to show tables : \dt
# to show data in table x : SELECT * FROM x;
# to exit : \q
|
Backup/Restore a dockerized PostgreSQL database
1
2
3
4
5
6
7
8
9
10
11
|
# The following command will dump all data from all tables:
docker exec <container_name> pg_dump -U <user> <schema_name> > backup
docker exec postgresql pg_dump -U postgres new_db > ./data/backups/backup.sql
# The following command will dump only inserts from all tables:
docker exec <container_name> pg_dump --column-inserts --data-only -U <user> <schema_name> > inserts.sql
docker exec postgresql pg_dump --column-inserts --data-only -U postgres new_db > ./data/backups/inserts.sql
# To backup gziped DB new_db in container named postgresql
mkdir ./data/backups/
docker exec postgresql pg_dump -U postgres -F t new_db | gzip > ./data/backups/new_db-$(date +%Y-%m-%d).tar.gz
|
Backup database
generate sql:
1
|
docker exec -t your-db-container pg_dumpall -c -U your-db-user > dump_$(date +%Y-%m-%d_%H_%M_%S).sql
|
to reduce the size of the sql you can generate a compress:
1
|
docker exec -t your-db-container pg_dumpall -c -U your-db-user | gzip > ./dump_$(date +"%Y-%m-%d_%H_%M_%S").gz
|
Restore database
1
2
|
cat your_dump.sql | docker exec -i your-db-container psql -U your-db-user -d your-db-name
cat ./conf/init-scripts/inserts.sql | docker exec -i 9e2929203d0278cc944ee01bcefce58f6e5e222c26350ebff9c355e12365a265 psql -U your-db-user -d your-db-name
|
to restore a compressed sql:
1
|
gunzip < your_dump.sql.gz | docker exec -i your-db-container psql -U your-db-user -d your-db-name
|