- PVSM.RU - https://www.pvsm.ru -
В этом руководстве я расскажу о практическом опыте переноса базы данных из MySQL 8 в PostgreSQL 16.
Исходные данные:
Приложение на Laravel 11, php 8.3 в Docker-контейнере
MySQL 8 в соседнем контейнере
Задача: перенос данных в AWS RDS PostgreSQL
Выбор инструмента миграции:
После исследования доступных решений выбор пал на pgloader (https://github.com/dimitri/pgloader [1]). Вот почему:
⭐ 6.2k stars на GitHub (самый популярный инструмент для такой задачи)
Последний коммит: 4 июня 2025 (проект немного, но поддерживается)
Открытые issues содержат множество готовых решений для типовых проблем
Альтернативы были рассмотрены, но:
Менее популярны
Хуже документированы
Имеют ограниченную поддержку
Однако при работе с pgloader был встречен ряд проблем, о решении которых напишу ниже.
Для работы pgloader требуется ряд зависимостей. В Dockerfile это выглядит так:
# Установка базовых зависимостей
RUN apt-get update &&
apt-get install -y
default-mysql-client
postgresql-client
make
sbcl
php8.3-pgsql
freetds-dev
freetds-bin
libssl-dev
libsqlite3-dev
Что мы устанавливаем:
default-mysql-client / postgresql-client — клиенты для работы с БД
make, sbcl — сборка pgloader из исходников
php8.3-pgsql— PHP-расширение для PostgreSQL (Laravel) в моем случае
freetds-* , ibssl-dev, libsqlite3-dev — дополнительные библиотеки, без них не удалось поставить pgloader из архива
1.2 Установка Pgloader версии 3.6.9
Стандартная установка через apt приводит к неожиданному результату:
apt-get install -y pgloader
pgloader --version
# Вывод: pgloader version "3.6.7~devel"
Даже при установке конкретной версии, все равно в итоге приходит 3.6.7. К сожалению при использовании версии 3.6.7 я получала ошибку, которая описана тут https://github.com/dimitri/pgloader/issues/1211 [2], как и ее решение - самостоятельно загрузить архив и скомпилировать верную версию.
# Загрузите последнюю версию
wget https://github.com/dimitri/pgloader/releases/download/v3.6.9/pgloader-bundle-3.6.9.tgz
# Распакуйте архив -tar -xvzf pgloader-bundle-3.6.9.tgz
cd pgloader-bundle-3.6.9/
make
sudo cp bin/pgloader /usr/local/bin/
hash -r
# Проверить версию
pgloader --version
# должно быть 3.6.9
В моём случае доступ к внешним ресурсам из контейнера был ограничен, поэтому пришлось использовать локальный архив pgloader-bundle-3.6.9.tgz, который я положила в корень проекта и добавила в git:
Dockerfile при этом выглядел так
COPY pgloader-bundle-3.6.9.tgz /tmp/
RUN tar -xzf /tmp/pgloader-bundle-3.6.9.tgz &&
cd pgloader-bundle-3.6.9 &&
make &&
cp bin/pgloader /usr/local/bin/
RUN rm -rf /tmp/pgloader-bundle-3.6.9*
В итоге у вас должна быть установлена версия pgloader 3.6.9
Распространенная ошибка при попытке запустить pgloader QMYND:MYSQL-UNSUPPORTED-AUTHENTICATION.
Варианты решений есть в https://github.com/dimitri/pgloader/issues/782 [3]
Мой итоговый вариант состоит из того, чтобы поменять аутентификацию для пользователя и изменить конфигурацию MySQL сервера.
3.1 Изменение метода аутентификации пользователя
Зайдите в контейнер MySQL.
mysql> ALTER USER 'sail_mysql'@'%' IDENTIFIED WITH mysql_native_password BY 'pAI';
# проверить
mysql> SELECT user, host, plugin, authentication_string FROM mysql.user;
# для нашего пользователя должно стоять mysql_native_password
3.1 Изменение конфигов на сервере
# проверка
mysql> SHOW VARIABLES LIKE 'default_authentication_plugin';
# будет caching_sha2_password, а нам надо mysql_native_password
# проверить откуда берет конфиги
bash-4.4# mysql --help | grep -A 1 "Default options"
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf
# cоздаем директорию /etc/mysql если ее нет
mkdir -p /etc/mysql
# cоздаем в /etc/mysql/my.cnf
cat > /etc/mysql/my.cnf << 'EOF'
[mysqld]
default_authentication_plugin = mysql_native_password
EOF
# cосмотрим содержимое
cat /etc/mysql/my.cnf 2>/dev/null || echo "Файл не создан"
Далее рестарт контейнера или сервиса mysql и проверяем еще раз, что переменные установились в native_password.
Перед началом миграции стоит убедиться, что pgloader сможет подключиться к обеим базам данных.
Эти проверки выполняются из того же контейнера, где будет работать pgloader. В моем случае это контейнер с самим приложением.
pgloader --version
mysql --version
mysql --host=mysql-1 --user=sail_mysql -p -e "USE tableName; SHOW TABLES;"
psql --version
psql --host=10.100.10.10 --username=user -d tableName -c "dt"
Моя итоговая команда
pgloader --dynamic-space-size 4096 --verbose
mysql://sail_mysql:passwordI@mysql-1:3306/tableName
postgresql://user:password@10.100.10.10:5432/tableName
Структура подключения:
<тип_бд>://<пользователь>:<пароль>@<хост>:<порт>/<имя_базы>
--verbose — подробный вывод для отладки
--dynamic-space-size 4096 — выделяем 4GB памяти для сборщика мусора Lisp-машины. Было добавлено из-за ошибки Heap exhausted during garbage collection, решение которой описано в https://github.com/dimitri/pgloader/issues/962 [4]
И вуаля, у меня миграция данных прошла успешно.
Для тех у кого приложение на Laravel, возможно будут полезны следующие шаги.
DB_CONNECTION=pgsql
DB_HOST=10.100.10.10 # IP вашего удалённого сервера
DB_PORT=5432
DB_DATABASE=tableName
DB_USERNAME=user
DB_PASSWORD=password
'pgsql' => [
...
'search_path' => 'public', // Важно: указываем правильную схему
],
# проверить схему, можно так
psql --host=postgres --username=user -d tableName -c "dt *.migrations"
Проверка, что удачно подключились
# Проверяем подключение
php artisan db:show
# Проверяем миграции
php artisan migrate:status
# Все миграции должны быть в статусе "Run"
Проверить все конструкции типа ->selectRaw(), ->whereRaw(), ->orderByRaw(), ->groupByRaw() на предмет неупотребляемых выражений в PostgreSQL.
Надеюсь эта статья была для вас полезна и вы успешно решите свою задачу.
Автор: koshaladka
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/pgloader/442641
Ссылки в тексте:
[1] https://github.com/dimitri/pgloader: https://github.com/dimitri/pgloader
[2] https://github.com/dimitri/pgloader/issues/1211: https://github.com/dimitri/pgloader/issues/1211
[3] https://github.com/dimitri/pgloader/issues/782: https://github.com/dimitri/pgloader/issues/782
[4] https://github.com/dimitri/pgloader/issues/962: https://github.com/dimitri/pgloader/issues/962
[5] Источник: https://habr.com/ru/articles/987922/?utm_source=habrahabr&utm_medium=rss&utm_campaign=987922
Нажмите здесь для печати.