среда, 23 марта 2011 г.

Ещё о репликации

Есть сервер, надо поднять ему slave.
Раньше была команда load data from master, но потом её объявили deprecated. Сейчас 2 метода:
1) rsync/csync2/etc
2) dump - restore

Оба сервера должны быть предварительно подготовлены -- создан юзер для репликации, прописаны server-id, bin-log итд.
На слейве - прописаны базы/таблицы для репликации.
Если сихронизировать через rsync, базы на слейве надо предварительно создать, причём крайне желательно, чтобы такие параметры как язык совпадал. Движок (engine) совпадать должен обязательно! И так не получится перенести innodb. Для dump можно указать ключ
Пользователи и права переносятся руками.

Любые такие операции выполняются с flush tables with read lock, show master status

По идее, можно остановить мастер, выполнить файловую синхронизацию.. но как в этом случае узнать позицию в логе? А без неё не запустить репликацию, так что получили п.1

1) сихронизируем (пока без остановки - главное, перегнать основной объем);
flush, show, делаем синхронизацию, снова show чтобы проверить, что ничего не убежало, снимаем лок (unlock tables), меняем мастера.

Но тут обнаружилась проблема: первая синхронизация шла со скоростью порядка 10мбит/с (канал такой, но проектам хватает), а вот вторая...
sent 2751559 bytes received 2278456 bytes 3617.41 bytes/sec
3кб/с! Заняло это минут 20, что вызвало 500 ошибку. А изменений было относительно немного... Вывод - этот метод непригоден для нагруженных проектов, с часто изменяемыми данными. Да и просто большими базами. Но хорошо работает на копировании с slave-сервера, подробнее есть ниже (с остановкой sql_thread и переносом файлов). И только для myisam; innodb в режиме разделения по файлам.

2) dump
могут пригодиться ключи
--master-data - обязательный ключ. Включает в себя CHANGE MASTER TO - устанавливает позицию в логе итд. Можно дописать =1 или 2: при 1 CHANGE MASTER TO сменит мастера и позицию, при 2 CHANGE MASTER TO закомментирован и несёт скорее информативный характер.
--delete-master-logs - имеет смысл только если слейв 1 или для бэкапов.
--single-transaction - в 1 поток, это несколько быстрее, но ставит глобальный лок на некоторое время. Имеет смысл только с транзакционными движками типа InnoDB
--create-db - создать базу
--opt - ключ, который включает в себя массу других, наиболее часто применямых. Рекомендуемо. Впрочем, если верить ману, он включен по умолчанию.


Важный момент: если надо перенести больше 1 базы - позиция должна быть неизменной или для каждой заливки надо делать flush, dump, restore, иначе данные могут оказаться разными на разных серверах.

В man mysqldump описан ещё вариант создания слейва, если уже есть хотя бы один, искать описание --master-data
Приведу тут пересказ:
1. Остановить SQL поток на слейве
mysql> STOP SLAVE SQL_THREAD;
mysql> SHOW SLAVE STATUS;
Нужны поля Relay_Master_Log_File и Exec_Master_Log_Pos
2. Дампим данные
shell> mysqldump --master-data=2 --all-databases > dumpfile

3. запускаем слейв
mysql> START SLAVE;

4. На новом слейве загружаем дамп
shell> mysql < dumpfile 5. На новом слейве меняем мастера mysql> CHANGE MASTER TO
-> MASTER_LOG_FILE = 'file_name', MASTER_LOG_POS = file_pos;
Может потребоваться также задать такие значения как MASTER_HOST

Ещё момент - при использовании ZFS можно сделать lock, дождаться его (как?), сделать snapshot, получить master_pos, unlock. И теперь можно перекидывать данные или сам снапшот на другой сервер (если делаем полную копию)

12.5.2.1. CHANGE MASTER TO Syntax
CHANGE MASTER TO option [, option] ...

option:
MASTER_HOST = 'host_name'
| MASTER_USER = 'user_name'
| MASTER_PASSWORD = 'password'
| MASTER_PORT = port_num
| MASTER_CONNECT_RETRY = interval
| MASTER_LOG_FILE = 'master_log_name'
| MASTER_LOG_POS = master_log_pos
| RELAY_LOG_FILE = 'relay_log_name'
| RELAY_LOG_POS = relay_log_pos
| MASTER_SSL = {0|1}
| MASTER_SSL_CA = 'ca_file_name'
| MASTER_SSL_CAPATH = 'ca_directory_name'
| MASTER_SSL_CERT = 'cert_file_name'
| MASTER_SSL_KEY = 'key_file_name'
| MASTER_SSL_CIPHER = 'cipher_list'
http://dev.mysql.com/doc/refman/5.0/en/change-master-to.html

--размышления--

Вот есть у нас сервер, к примеру с десятком баз, реплицируется допустим 8. Как переносить базы на другой сервер, с минимальным простоем? Если делать к примеру mysqldump на каждую базу, то master-data будет показывать на разные записи. Что будет происходить при загрузке этих дампов? Как обеспечить тогда синхронность данных? Делать после каждой заливки slave start,...,slave stop и следующую заливать? Залить просто все, потом на slave start оно само выровняет? Сомневаюсь.
Обидно, что нет команды resync например, чтобы сервер сам проверил все записи и нужные слил. Важно, чтобы еще с innodb работало. С инной даже проще - делаем транзакцию (и получаем целостный набор данных), и сохраняем в переменные текущую лог-позицию. После синхронизации завершаем транзакцию и выставляем лог. Причем для оперативности можно relay-log с текущей позиции сразу вести, и по окончанию перелива быстро прогнать его.

Комментариев нет:

Отправить комментарий