やる気がストロングZERO

やる気のストロングスタイル

ローカル環境にて使用DBをmysqlからpostgresqlに変更

ローカル開発環境にて djangoのmigrateを触っていて実行に失敗した。 mysqlだとmigrateが失敗したとき、DBが中途半端に変更がされた状態になってしまう。 こうなってしまうと、migrateの失敗の原因を取り除いてmigrate再実行しても成功しない。 手動でDBの状態を元に戻す必要がある。

postgresqlなら変更をtransactionの中で行ってくれるので、上記のような問題は起こらない。

参考)https://docs.djangoproject.com/ja/2.0/topics/migrations/#mysql

なので、DBをmysqlからpostgresqlに変更することにした。 以下がその手順内容である。

手順

  • macpostgresqlをインストールする
  • macpostgresql自動起動するようにする
  • GUIクライアントソフト(PSequel)をインストールする
  • postgresqlにDBを作成してPSequelから接続してみる。
  • djangoのDBをmysqlからpostgresqlに変更する
  • migrateを実行してpostgresqlに必要なtableを作成する。
  • mysqlからmysqldumpでデータを抜き出す。
  • postgresqlにデータを挿入する
  • (自動採番設定がされている場合)自動採番の開始番号をテーブルのIDの最大値に設定する

macpostgresqlをインストールする、macpostgresql自動起動するようにする

$ brew install postgresql
$ brew services start postgresql

参考)https://qiita.com/takuya0301/items/c0720753de98572703b8

GUIクライアントソフト(PSequel)をインストールする

http://www.psequel.com/

postgresqlにDBを作成してPSequelから接続してみる。

データベース作成

$ createdb [db名]

データベースが作成されているか確認

$ psql -l

PSequelから以下内容で接続出来ることを確認する

Host:localhost
User:macのユーザー名
Password:設定してないので空
Database:作成したdb名

djangoのDBをmysqlからpostgresqlに変更する

settings.pyのDATABASESの内容を以下のように変更する

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': '作成したdb名',
        'USER': 'macのユーザー名',
        # 'PASSWORD': '', # 設定していないので空
        'HOST': '', # (ローカルホストなら空でOK)
        'PORT': '', # (デフォルトポートなら空でOK)
    }
}

migrateを実行してpostgresqlに必要なtableを作成する

./manage.py migrate

mysqlからmysqldumpでデータを抜き出す

$ mysqldump -uroot -p -hlocalhost --no-create-db --no-create-info --compatible=postgresql [DB名] [Table名] [Table名]… > 出力先ファイル名

postgresqlにデータを挿入する

mysqldumpで出力したsqlpostgresqlで実行する このとき、LOCK TABLES "テーブル名"の行が、エラーとなったので、 INSERT行以外は削除して適用した。

自動採番設定がされている場合)自動採番の開始番号をテーブルのIDの最大値に設定する

自動採番設定がされているテーブルの場合、 上記の方法でデータ挿入したあとにinsertを行うとエラーが出て失敗する場合がある。 自動採番によりid=1としてレコード挿入が行われようとするが、既に既存データにid=1が存在する、というような状況になる場合がある。

このときは、自動採番を今存在しているレコードのidの最大値に設定してやることで解決する。

postgresqlで以下を実行する

SELECT setval('[table名]_id_seq', (SELECT MAX(id) FROM [table名]));