План переноса данных

Краткое описание

  1. Исправить код МС на Postgres
  2. Создать БД
  3. Сделать чистую миграцию - только схема
  4. Остановить МС
  5. Запустить pgloader, который перенесет данные
  6. Переключить конфиг МС на Postgres и запустить МС

Подробное описание на примере переезда одного микросервиса us-mortgage

Исправить код МС на Postgres

Локально: переключить проект на Postgres, запустить тесты, сделать смоук-тест.

План перевода

Если проект был форкнут от us-template, тогда достаточно

git remote add template git@******:usbsite/services/us-template.git
git fetch template laravel-10.x-latest
git merge --no-commit --no-ff template/laravel-10.x-latest
# Исправление конфликтов и измененных значений

Если это не так, то можно копировать из us-template готовые участки кода по плану:

[ ] .env.dist: подключения, порты
[ ] docker-compose.yml: поправить секции laravel-app, postgres, удалить mysql
[ ] docker/laravel-app/Dockerfile: добавлена секция для postgresql-client
[ ] docker/mysql: удалить
[ ] docker/postgres: добавить
[ ] docker/workspace/home/.my.cnf.dist: удалить
[ ] docker/workspace/home/Xzibit/.zshrc: поправить (там было прописывание конфига .my.cnf.dist)
[ ] src/laravel-app/config/database.php: удалить mysql, добавить pgsql, в том числе CI-подключения
[ ] src/laravel-app/config: найти 'mysql', заменить на 'pgsql'
[ ] src/laravel-app/phpunit.xml.dist: заменить на ci_test_pgsql
[ ] поправить миграцию 'jwt_public_keys', в ней исправлена строка 'key'. Внимание! При миграции данных следует исключить таблицу jwt_public_keys, иначе будут будут перенесены данные, которые приведут к ошибкам
[ ] /src/laravel-app/.env, .env.dist: - поправить DB_*, а лучше сделать пустыми файлами, чтобы не было перезатирания env
[ ] миграции: добавить индексы для FK
[ ] миграции: изменить тип поля json => jsonb, binary => longText/jsonb
[ ] Laravel-query-builder: поправить фильтры ('members.uuid' => AllowedFilter::exact('members.uuid'))

Более тщательные проверки можно делать после переезда на develop/test окружениях.

Foreign key

MySQL по-дефолту при создании FK также создает индекс на это поле. Однако Postgres этого не делает по-умолчанию. Но индексы нужны. Поэтому необходимо проверить, и при необходимости сделать миграцию для их создания.

Создать БД

Можно воспользоваться скриптом для генерации SQL, либо использовать сниппет ниже.

-- Создание БД для тестов на сервере develop
 
CREATE DATABASE "ci-us-template";
CREATE DATABASE "ci-us-template-develop";
CREATE DATABASE "ci-us-template-test";
CREATE DATABASE "ci-us-template-pre-production";
CREATE DATABASE "ci-us-template-production";
 
ALTER DATABASE "ci-us-template" OWNER TO "ci-test";
ALTER DATABASE "ci-us-template-develop" OWNER TO "ci-test";
ALTER DATABASE "ci-us-template-test" OWNER TO "ci-test";
ALTER DATABASE "ci-us-template-pre-production" OWNER TO "ci-test";
ALTER DATABASE "ci-us-template-production" OWNER TO "ci-test";
 
-- На сервере develop
 
CREATE USER "svc-us-template-develop" WITH PASSWORD '*****';
CREATE USER "svc-us-template-test" WITH PASSWORD '*****';
 
CREATE DATABASE "us-template-develop";
CREATE DATABASE "us-template-test";
 
GRANT "svc-us-template-develop" TO site_admin;
GRANT "svc-us-template-test" TO site_admin;
ALTER DATABASE "us-template-develop" OWNER TO "svc-us-template-develop";
ALTER DATABASE "us-template-test" OWNER TO "svc-us-template-test";
 
\c "us-template-develop";
GRANT ALL PRIVILEGES ON DATABASE "us-template-develop" TO "svc-us-template-develop";
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "svc-us-template-develop";
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO "svc-us-template-develop";
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO "svc-us-template-develop";
 
\c "us-template-test";
GRANT ALL PRIVILEGES ON DATABASE "us-template-test" TO "svc-us-template-test";
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "svc-us-template-test";
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO "svc-us-template-test";
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO "svc-us-template-test";
 
-- На сервере prod
 
CREATE USER "svc-us-template-pre-production" WITH PASSWORD '****************';
CREATE USER "svc-us-template-production" WITH PASSWORD '****************';
 
CREATE DATABASE "us-template-pre-production";
CREATE DATABASE "us-template-production";
 
GRANT "svc-us-template-pre-production" TO site_admin;
GRANT "svc-us-template-production" TO site_admin;
ALTER DATABASE "us-template-pre-production" OWNER TO "svc-us-template-pre-production";
ALTER DATABASE "us-template-production" OWNER TO "svc-us-template-production";
 
\c "us-template-pre-production";
GRANT ALL PRIVILEGES ON DATABASE "us-template-pre-production" TO "svc-us-template-pre-production";
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "svc-us-template-pre-production";
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO "svc-us-template-pre-production";
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO "svc-us-template-pre-production";
 
\c "us-template-production";
GRANT ALL PRIVILEGES ON DATABASE "us-template-production" TO "svc-us-template-production";
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "svc-us-template-production";
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO "svc-us-template-production";
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO "svc-us-template-production";

Сделать чистую миграцию - только схема

На локальной машине разработчика проверить, что везде используется подключение «pgsql» (databases.php, queue.php и telescope.php).

Временно добавить следующие строки в подключение «pgsql»:

'host' => '******',
'port' => '5432',
'database' => 'us-template-develop',
'username' => 'svc-us-template-develop',
'password' => '******',

Запустить миграцию: в результате появится чистая база данных.

art migrate

В некоторых проектах туда добавляются первоначальные данные, но это не важно - они будут снесены далее.

Зачем это делать? Утилита pgloader может самостоятельно мигрировать схему, однако это потребует много времени по ее настройке. Например, будет проблема с unsigned. Проще сделать миграцию и перенести только данные.

Остановить МС

Делается через GitLab. Нужно, чтобы не была нарушена ссылочная целостность.

Запустить pgloader, который перенесет данные

Создать файл migrate-mortgage-data.load на сервере Postgres.

Его примерное содержимое:

LOAD DATABASE
 FROM mysql://USER:PASSWORD@mysqlhost/us-mortgage-develop
 INTO postgresql://USER:PASSWORD@localhost/us-mortgage-develop
 
 WITH data only, truncate, reset sequences
 SET maintenance_work_mem to '128MB', work_mem to '12MB', search_path to 'public'
  
 BEFORE LOAD DO $$ ALTER SCHEMA public RENAME TO "us-mortgage-develop"; $$
 AFTER LOAD DO $$ ALTER SCHEMA "us-mortgage-develop" RENAME TO "public"; $$
 
 EXCLUDING TABLE NAMES MATCHING ~/telescope_/, ~/failed_jobs/, ~/jwt_public_keys/
;

pgloader работает со схемой, которая должна совпадать с названием БД, поэтому вначале схема переименовывается, а затем возвращается назад в public.

Также происходит truncate, иначе при миграции могут быть ошибки - если artisan migrate делает первоначальное наполнение данными.

Запуск миграции:

pgloader migrate-mortgage-data.load

Необязательно, но желательно прописать search_path для базы данных. Делается это после переноса данных:

ALTER DATABASE "us-template-develop" SET search_path TO "public";

Более подробная информация о самой утилите приведена тут.

Переключить конфиг МС на Postgres и запустить МС

Список переменных, которые следует исправить на dev/test:

app:
  dev_mysql_credential: false
  db_host: "******"
  env:
    - name: DB_DATABASE
      value: us-template-develop
    - name: DB_USERNAME
      value: svc-us-template-develop
    - name: DB_PASSWORD
      value: "******"

Список переменных, которые следует исправить на pre-prod/prod:

app:
  dev_mysql_credential: false
  db_host: "******"
  env:
    - name: DB_DATABASE
      value: us-template-production
    - name: DB_USERNAME
      value: svc-us-template-production
    - name: DB_PASSWORD
      value: "*********"
    - name: DB_CONNECTION
      value: "pgsql"
    - name: DB_PORT
      value: "5432"
Не допускайте ошибок в прод-конфигурации. Нужно проверить, что нет дублей переменных DB_ ниже в файле, DB_CONNECTION=pgsql, DB_PORT=5432.
Печать/экспорт