delhi09の勉強日記

技術トピック専用のブログです。自分用のメモ書きの投稿が多いです。あくまで「勉強日記」なので記事の内容は鵜呑みにしないでください。

Djangoで複数のDBを使用する方法について検証する(usingを使う場合)

Djangoで複数のDBを使用して、向き先を切り替える方法について検証した。

公式ドキュメントは以下
docs.djangoproject.com

理由

本番で稼働させるWEBアプリケーションでは、負荷分散のためにread-onlyのRDBと書き込み用のRDBの複数台構成にして、複数のDB間で向き先を切り替えるという場面が結構あると思われるので、Djangoで実現する方法について調べておく。

やること

以下の図のように、DjangoからMySQL1号機とMySQL2号機にそれぞれ別々のUserデータをinsertする。
※ あくまで実現方法の検証なので、細かい設定はしない。

f:id:kamatimaru:20200516060813p:plain

Docker Compose

検証用のMySQLにはDockerコンテナを使用する。

[docker-compose.yml]

version: "3"

services:
    db_server1:
        image: mysql:5.7
        ports: 
            - "3306:3306"
        environment: 
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: sample
    
    db_server2:
        image: mysql:5.7
        ports: 
            - "3307:3306"
        environment: 
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: sample

settings.py

settings.pyには以下のように設定を2つ書く。
デフォルトでは「default」に設定したDBが使用される。

[settings.py]

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "sample",
        "USER": "root",
        "PASSWORD": "password",
        "HOST": "127.0.0.1",
        "PORT": "3306",
    },
    "dbserver2": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "sample",
        "USER": "root",
        "PASSWORD": "password",
        "HOST": "127.0.0.1",
        "PORT": "3307",
    },
}

マイグレーション

まずはDockerコンテナを起動する。

$ docker-compose up -d


次に、マイグレーションを実行する。

何もオプションを付けずにマイグレーションを実行すると、「default」のDBのみにマイグレーションが適用される。
「default」以外のDBにマイグレーションを適用する場合は、オプションで対象のDBを指定する必要がある。

$ python manage.py migrate #「default」に対してマイグレーションを適用
$ python manage.py migrate --database=dbserver2 #「dbserver2」に対してマイグレーションを適用

views.py

views.pyに以下のように検証用のコードを書く。

[views.py]

from django.contrib.auth.models import User
from django.http import HttpResponse


def index(request):
    user1 = User(username="fizz")
    user1.set_password("password")
    user1.save()

    user2 = User(username="buzz")
    user2.set_password("password")
    user2.save(using="dbserver2")
    return HttpResponse("Hello, world. You're at the polls index.")

「default」ではないDBにデータをinsertする場合は、saveの引数に「using=${DB名}」を指定する。

user2.save(using="dbserver2")

検証

サーバーを起動してhttp://127.0.0.1:8000/polls/にアクセスする。

その後、データを確認する。

・MySQL1号機

mysql> select id, username from auth_user;
+----+----------+
| id | username |
+----+----------+
|  1 | fizz     |
+----+----------+
1 row in set (0.00 sec)

mysql>

・MySQL2号機

mysql> select id, username from auth_user;
+----+----------+
| id | username |
+----+----------+
|  1 | buzz     |
+----+----------+
1 row in set (0.00 sec)

mysql>

以上で検証完了。

検証用のコードは以下
https://github.com/kamatimaru/multiple_databases_practice

公式ドキュメントによると、ルーターという機能を使うやり方もあるそうなので、別の機会に検証する。
docs.djangoproject.com