На примере базы сдвора разбираем процесс перехода с mysql на postgresql

  • создаем базу на постгрес

    1
    2
    sudo -u postgres psql
    create database pgdatabasename;
  • делаем виртуальное окружение для питона 2.7 и скачиваем утилиту py-mysql2pgsql

    1
    2
    3
    virtualenv -p $(which python2.7) --no-site-packages ~/envs/py-mysql2pgsql
    source ~/envs/py-mysql2pgsql/bin/activate
    pip install py-mysql2pgsql
  • запускаем

    1
    py-mysql2pgsql -v

В консоли видим ошибку, что конфига нет. Все верно, мы создали его этой командой.
Открываем для правки любым текстовым редактором.

1
vi mysql2pgsql.yml

оставляем структуру как есть, правим часть с базами

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql:
hostname: хост mysql, лучше сдампить и перевести на локалхост
port: 3306
socket: оставляем пустым
username: mysqluser
password: mysqlpass
database: mysqldatabasename
compress: false
destination:
file: оставляем пустым - если указать, будет записывать в файл
postgres:
hostname: localhost
port: 5432
username: pguser
password: pgpass
database: pgdatabasename

  • правим файл библиотеки утилиты (нужно чтобы не наткнуться на ошибку с переводом дат)
    \mysql2pgsql\lib\postgres_writer.py строка 72

меняем

1
elif column['type'] == 'datetime':

на

1
elif column['type'] == 'datetime' or column['type'].startswith('datetime('):

  • запускаем утилиту еще раз
    py-mysql2pgsql -v

натыкаемся на ошибку enum в базе shops

Правим колонки в mysql, заменяем enum на varchar

1
2
3
4
5
6
7
8
9
10
ALTER TABLE shops ADD new_type_address ENUM('magazin', 'rc', 'otdelprodazh', 'dist-point') DEFAULT 'magazin' NULL;
UPDATE shops SET new_type_address = type_address;
ALTER TABLE shops DROP type_address;
ALTER TABLE shops CHANGE new_type_address type_address VARCHAR(55) NULL;
ALTER TABLE shops ADD new_type_company ENUM ('sdvor', 'teplocentr') DEFAULT 'sdvor' NOT NULL;
UPDATE shops SET new_type_company = type_company;
ALTER TABLE shops DROP type_company;
ALTER TABLE shops CHANGE new_type_company type_company VARCHAR(55) NOT NULL;

Запускаем скрипт снова, базу можно не дропать

в процессе можно наткнуться на такую ошибку
psycopg2.IntegrityError: insert or update on table “cart_items” violates foreign key constraint “cart_items_cart_id_fkey”
DETAIL: Key (cart_id)=(226567) is not present in table “cart”.

и как аналог
psycopg2.IntegrityError: insert or update on table “orders_pickups” violates foreign key constraint “orders_pickups_order_id_fkey”
DETAIL: Key (order_id)=(49595) is not present in table “orders”.

Ошибка говорит о том, что заказа, на который ссылается самовывоз, не существует. Нам такие записи в базе не нужны (по причине того, что связаны с уже неактуальным заказом) и в этом случае удаляем строку с соответствующим key_id из таблицы cart_items или другой, по аналогии.

1
2
3
4
5
6
7
8
9
10
11
DELETE ci FROM cart_items ci LEFT outer join cart c on c.id = ci.cart_id
where c.id is NULL
DELETE opk FROM orders_pickups opk LEFT outer join orders o on o.id = opk.order_id
where o.id is NULL
DELETE opr FROM orders_products opr LEFT outer join orders o on o.id = opr.order_id
where o.id is NULL
DELETE osh FROM orders_statuses_history osh LEFT outer join orders o on o.id = osh.order_id
where o.id is NULL

  • Если все прошло успешно, то у нас есть готовая база постгреса.

Меняем database ENGINE в сеттингах джанги на psycopg2, делаем makemigrations и migrate, сносим конфликтующие миграции (в случае сдвора были миграции orders и banners)