УСТАНОВКА

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

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

    DATABASE_ENGINE = 'mysql_replicated'
    DATABASE_HOST = 'master.db'
    DATABASE_PORT = ''
    DATABASE_SLAVE_HOST = 'slave.db'
    DATABASE_SLAVE_USER = '...'
    DATABASE_SLAVE_PASSWORD = '...'
    

    Если какая-то slave-настройка не указана, то она берется из соответствующей master-настройки.

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

    SESSION_ENGINE = 'mysql_replicated.sessions'
    

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

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

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

Middleware

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

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

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

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

Декораторы

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

from mysql_replicated.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():
    # запись в БД

Отключение переключений

Бывают ситуации, когда переключение соединений нужно временно отключить. Самый простой пример -- тестирование кода, когда для изоляции данных в тестах используются бескоммитные транзакции. При вызове каждого отдельного теста начинает работать мастер-соединение, через которое устанавливаются fixtures. Затем по ходу теста код может переключиться в slave-соединение, которое не видит изменений, сделанных через мастер, а значит получает пустую БД -- тесты падают.

В таких случаях переключение соединений можно отключить:

from django.db import connection
connection.state_change_disabled = True

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