Бэкенд mysql_cluster нужен для использования Django в схеме с master-slave репликацией MySQL. Он умеет переключать глобальное соединение Джанго с БД между мастером и slave-репликами, и тем самым позволяет использовать стандартный ORM.

Скачать версия 1.0

УСТАНОВКА

  1. Поставить mysql_cluster в питоновский путь (обычный способ "python setup.py install" работает).

  2. Указать в настройках название бэкенда и хосты с портами мастера и реплики:

    DATABASE_ENGINE = 'mysql_cluster'
    DATABASE_HOST = 'master.db'
    DATABASE_PORT = ''
    DATABASE_SLAVE_HOST = 'slave.db'
    DATABASE_SLAVE_PORT = DATABASE_PORT
    

    (Настройки DATABASE_SLAVE_* обязательны.)

  3. Если используются джанговские сессии с хранением в БД, то почти без вариантов имеет смысл указать в качестве движка сессий класс из mysql_cluster. Он полностью совместим со стандартным, просто явно использует для доступа к сессиям мастер-соединение.

    SESSION_ENGINE = 'mysql_cluster.sessions'
    

ИСПОЛЬЗОВАНИЕ

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

  • write-операции происходят тогда, когда активно мастер-соединение
  • слейв-соединение активируется для тех read-операций, для которых это имеет смысл

Тем не менее, на практике все не так сложно.

Middleware

Если ваш проект строится в соответствие с принципами HTTP, где GET-запросы не производят изменений в данных системе (за исключением всяких сторонних эффектов), то большая часть работы делается включением middleware из пакета:

MIDDLEWARE_CLASSES = [
    # ...
    'mysql_cluster.middleware.ReplicationMiddleware',
    # ...
]

Фактически оно включает на время выполнения GET-запросов слейв-соединение, а на POST (а также PUT, DELETE и все другое) — мастер-соединение. Этого обычно достаточно для большинства случаев.

Но есть случаи, когда доступ в БД случается не в рамках основной логики. Например создание сессиий, запись какой-нибудь статистики, прозрачная регистрация пользователя где-нибудь внутри системы. Это может случаться в произвольные моменты времени, в том числе и при GET-запросах. Решается это так:

  • Если второстепенные записи делаются в какой-то другой middleware, то достаточно поставить ее в списке MIDDLEWARE_CLASSES перед ReplicationMiddleware. В этом случае работа вашей middleware будет происходить до логики переключения через соединение по умолчанию — мастер.

  • Иначе всегда можно явно переключить бэкенд в мастер-соединение (см. "Ручное управление" дальше).

Декораторы

Помимо ReplicationMiddleware, работающей для всех запросов, в пакете есть еще декораторы для отдельных view, которые позволяют явно сказать, что конкретная view работает с мастером или с репликой. Используются просто:

from mysql_cluster.decorators import use_master, use_slave

@use_master
def my_view(request, ...):
    # используется мастер-соединение для все операций с БД на время
    # работы view (если явно не переопределено).

@use_slave
def my_view(request, ...):
    # то же для реплик

GET после POST

Есть отдельный момент в работе с репликацией в том, что реплики при обновлениях могут слегка отставать от мастера. На практике это выливается в то, что после сабмита POST-формы, которая возвращает HTTP-редирект на страницу с обновленными данными, эта страница может считаться из еще не обновленной реплики, и пользователь увидит, что его действие не сработало.

Для борьбы с этим эффектом и ReplicationMiddleware, и декораторы поддерживают специальную логику, по которой обслуживание следующего GET'а после POST'а с редиректом явно заворачивается в мастер.

Ручное управление

Любой код, который пишет в БД, но при этом выполняется в непредсказуемые моменты времени, можно явно завернуть в мастер соединение. Делается это так:

from django.db import connection
connection.use_master()
try:
    # запись в БД
finally:
    connection.revert()

Или, если вы используете Питон версии от 2.5 и новее, то короче:

from django.db import connection
with connection.use_master():
    # запись в БД

Статистика

В отладочном режиме к стандартной статистике выполненных запросов бэкенд добавляет еще один параметр "db", который может иметь значения "master" или "slave".

from django.db import connection
print connection.queries[-1]['db']

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

Инсталляции

Сайты, где используется mysql_cluster