Django: Каковы наилучшие методы миграции проекта из sqlite в PostgreSQL

Мне нужно перенести сложный проект из sqlite в PostgreSQL. У многих людей проблема с внешними ключами, усечение данных и т.д....

  • Есть ли полная автоматическая утилита?
  • Нужно ли проверять некоторые данные или схему перед переносом?

Изменить: я пробовал django-command-extensions DumpScript, но он не работает на моем 2 ГБ оперативной памяти с текущим DataSet.

Ответ 1

По моему опыту, сбрасывание и восстановление из SQL не работает должным образом.

Вместо этого выполните следующие действия:

1. Содержимое dump db для json

$ ./manage.py dumpdata > dump.json

2. Переключите бэкэнд в settings.py

DATABASES = {
    # COMMENT OUT:
    # 'default': dj_database_url.config(default='sqlite:////full/path/to/your/database/file.sqlite'),
    # ADD THIS INSTEAD:
    'default': dj_database_url.config(default='postgres://localhost:5432/postgres_db_name'),
}

3. Syncdb и перенести новую БД в ту же структуру таблицы

$ ./manage.py syncdb
$ ./manage.py migrate

4. Загрузите json в новый db.

$ ./manage.py loaddata dump.json

5. Congrats! Теперь новые данные находятся в вашем postgres db.

Ответ 2

Ниже приводится уточнение ответа Нимо и ответ Стивена для Django 1.7 +:

  • ./manage.py dumpdata --natural-primary --natural-foreign > dump.json
  • Измените DATABASES в settings.py, чтобы указать на новый (PostgreSQL) db.
  • ./manage.py migrate
  • ./manage.py loaddata dump.json

Одна из проблем, с которыми я столкнулась, заключается в том, что SQLite, похоже, фактически не обеспечивает максимальную длину для CharField s. В моем случае это сделало шаг loaddata неудачным. Мне удалось найти (и удалить) экземпляры модели со слишком длинными значениями CharField с помощью:

MyModel.objects.extra(where=["LENGTH(text) > 20"]).delete()

Как только я сделал это до шага 1. выше, все сработало.

Ответ 3

Мне никогда не приходилось это делать, но я бы попробовал.

  • Остановить работу серверов
  • python manage.py dumpdata​​li >
  • Измените settings.py, чтобы указать на недавно созданную базу данных postgres
  • python manage.py loaddata​​li >

Ответ 4

Другим способом сделать это может быть использование нескольких баз данных.

http://docs.djangoproject.com/en/dev/topics/db/multi-db/

Важно, чтобы вы прочитали этот раздел.

http://docs.djangoproject.com/en/dev/topics/db/multi-db/#moving-an-object-from-one-database-to-another

Из того, что я понимаю, это означает, что если в вашей новой базе данных нет данных, из светильников, например, вы могли бы сделать

queryset = MyModel.objects.using("old-db").all()
for obj in queryset:
    obj.save(using="new-db")

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

Ответ 5

Согласно ответу @Nimo, используемому из "syncdb", "syncdb" не работает в Django 1.9 и более поздних версиях (это работает в Django 1.7)

Вместо этого используйте команду ниже:

python manage.py migrate


И настройка конфигурации Postgres здесь:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

Ответ 6

Прежде всего, я просто попробую просто:

sqlite3 sqllitedb .dump | psql postgresdb

В этот момент просто проверьте это. Напишите несколько тестовых скриптов в Django для вывода набора выборочных записей для каждого приложения, а затем выполните diff, чтобы убедиться, что они идентичны. Если они есть, то ваше преобразование, вероятно, прекрасно.

Если это не работает...

Я бы рекомендовал не использовать Django для дампа и загрузки данных, так как я предполагаю, что он не оптимизирован для этого.

Вместо этого я бы создал вторую версию вашего приложения с правильными настройками базы данных PostgreSQL, запустил syncdb для создания всех таблиц, а затем скопировал данные из mysqllite в PostgreSQL с помощью другого инструмента.

Дело в том, что большинство проблем при преобразовании данных в определения таблиц и т.д. Это, по-видимому, самое необычное. Если вы можете создать SQL script, который является дампом только содержимого таблицы, это должно быть довольно стандартными командами SQL INSERT INTO.

Честно говоря, я не понимаю, почему возникнут проблемы с иностранным ключом. Предполагая, что sqlite создает точные внешние ключи (и почему бы и нет?), Тогда нет способа, который бы не копировал правильно. Действительно, внешние ключи не являются особыми формами данных. Не более вероятно, что поле UserProfile.user_id будет содержать неправильное значение, чем поле UserProfile.photo. Если внешний вопрос состоит в том, что сами поля неправильно идентифицированы как поля внешнего ключа (т.е. Никаких ограничений), тогда проблема с первым созданием базы данных с использованием syncdb будет решать эту проблему.

В соответствии с усечением: как я понимаю, PostgreSQL выдает жесткую ошибку, если данные будут усечены. Я не знаю, так ли это в случае с sqlite или если он просто усекает молча. В любом случае, опять же, предполагая, что sqlite не каким-то образом перетаскивает данные на экспорт, поля должны содержать данные, которые являются надлежащей длиной для поля, в котором он находится. Единственное, что я могу думать об этом, может повлиять на это кодирование символов, поэтому make что поля PostgreSQL имеют одинаковую кодировку, как это делают таблицы sqlite, по крайней мере во время импорта.

Ответ 7

Что мне помогло, так это запустить сиквел от ruby. Просто запустите команду:

gem install sequel

Вам необходимо установить в своей системе пакеты devel для postgres, sqlite и ruby. Запустите команду:

gem install pg sqlite3

Создайте пустую базу данных на postgresql, скажем, testDB и назначьте разрешение на предоставление пользователю. Из командной строки запустите:

sequel -C sqlite:///path/to/sqlitedb.db postgres://user:[email protected]/testDB

Это будет работать без ошибок.

Измените настройки в вашем проекте django для работы с базой данных postgres.

./manage migrate (not necessary)

Запустите сервер