УСТАНОВКА
Поставить mysql_replicated в питоновский путь (обычный способ "python setup.py install" работает).
Указать в настройках название бэкенда и хосты с портами мастера и реплики:
DATABASE_ENGINE = 'mysql_replicated' DATABASE_HOST = 'master.db' DATABASE_PORT = '' DATABASE_SLAVE_HOST = 'slave.db' DATABASE_SLAVE_USER = '...' DATABASE_SLAVE_PASSWORD = '...'Если какая-то slave-настройка не указана, то она берется из соответствующей master-настройки.
Если используются джанговские сессии с хранением в БД, то почти без вариантов имеет смысл указать в качестве движка сессий класс из mysql_replicated. Он полностью совместим со стандартным, просто явно использует для доступа к сессиям мастер-соединение.
SESSION_ENGINE = 'mysql_replicated.sessions'
ИСПОЛЬЗОВАНИЕ
Mysql_replicated устроен так, что переключение между мастером и репликами должно делаться явно, оно не происходит автоматически в зависимости от типа SQL-запроса или доступа к какой-то определенной таблицы и т.д. Поэтому на голову программиста ложится ответственность за то, чтобы следить за тем, что
- write-операции происходят тогда, когда активно мастер-соединение
- слейв-соединение активируется для тех read-операций, для которых это имеет смысл
Тем не менее, на практике все не так сложно.
Middleware
Если ваш проект строится в соответствие с принципами HTTP, где GET-запросы не производят изменений в данных системе (за исключением всяких сторонних эффектов), то большая часть работы делается включением middleware из пакета:
MIDDLEWARE_CLASSES = [
# ...
'mysql_replicated.middleware.ReplicationMiddleware',
# ...
]
Фактически оно включает на время выполнения GET-запросов слейв-соединение, а на POST (а также PUT, DELETE и все другое) — мастер-соединение. Этого обычно достаточно для большинства случаев.
Но есть случаи, когда доступ в БД случается не в рамках основной логики. Например создание сессиий, запись какой-нибудь статистики, прозрачная регистрация пользователя где-нибудь внутри системы. Это может случаться в произвольные моменты времени, в том числе и при GET-запросах. Решается это так:
Если второстепенные записи делаются в какой-то другой middleware, то достаточно поставить ее в списке MIDDLEWARE_CLASSES перед ReplicationMiddleware. В этом случае работа вашей middleware будет происходить до логики переключения через соединение по умолчанию — мастер.
Иначе всегда можно явно переключить бэкенд в мастер-соединение (см. "Ручное управление" дальше).
Декораторы
Помимо 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 бэкенд при всех переключениях
использует текущее соединение. Соответственно, снятие флажка снова разрешает
переключение.