Сохранение целостности между двумя отдельными хранилищами данных во время резервного копирования (MySQL и MongoDB) - PullRequest
11 голосов
/ 08 марта 2012

У меня есть приложение, которое я разработал, где реляционные данные находятся и естественно вписываются в MySQL. У меня есть другие данные, которые имеют постоянно развивающуюся схему и не имеют реляционных данных, поэтому я решил, что естественным способом хранения этих данных будет использование MongoDB в качестве документа. Моя проблема здесь - один из моих документов, ссылающийся на первичный идентификатор MySQL. Пока что это работает без каких-либо проблем. Меня беспокоит то, что когда поступает производственный трафик и мы начинаем работать с резервными копиями, при изменении документа может возникнуть несогласованность, которая может указывать на неверный идентификатор в базе данных MySQL. Единственный способ гарантировать это в определенной степени - закрыть приложение и создать резервные копии, что не имеет большого смысла.

Должны быть другие люди, которые используют подобную стратегию. Каков наилучший способ обеспечения целостности данных между двумя хранилищами данных, особенно во время резервного копирования?

Ответы [ 3 ]

4 голосов
/ 26 марта 2012

MySQL Perspective

Все ваши данные MySQL должны будут использовать InnoDB.Затем вы можете сделать снимок данных MySQL следующим образом:

MYSQLDUMP_OPTIONS="--single-transaction --routines --triggers"
mysqldump -u... -p... ${MYSQLDUMP_OPTIONS} --all-databases > MySQLData.sql

Это создаст чистый моментальный снимок всех данных MySQL на момент времени в виде одной транзакции.

Например,, если вы запустите этот mysqldump в полночь, все данные в выводе mysqldump будут с полуночи.Данные все еще могут быть добавлены в MySQL (при условии, что все ваши данные используют InnoDB Storage Engine), и вы можете иметь MongoDB для ссылки на любые новые данные, добавленные в MySQL после полуночи, даже если это происходит во время резервного копирования.

Если у вас естьлюбые таблицы MyISAM, вам нужно преобразовать их в InnoDB.Давайте перейдем к погоне.Вот как вы создаете сценарий для преобразования всех ваших таблиц MyISAM в InnoDB:

MYISAM_TO_INNODB_CONVERSION_SCRIPT=/root/ConvertMyISAMToInnoDB.sql
echo "SET SQL_LOG_BIN = 0;" > ${MYISAM_TO_INNODB_CONVERSION_SCRIPT}
mysql -u... -p... -AN -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" >> ${MYISAM_TO_INNODB_CONVERSION_SCRIPT}

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

Перспектива MongoDB

Я не могу говорить за MongoDB, потому что знаю очень мало.Тем не менее, для стороны MongoDB, если вы устанавливаете набор реплик для любых данных MongoDB, вы можете просто использовать mongodump для реплики.Поскольку mongodump не является моментом времени, вам придется отключить реплику (чтобы не допустить повторения изменений), а затем выполнить mongodump для реплики.Затем восстановите реплику своему хозяину.Узнайте у ваших разработчиков или из 10gen, можно ли использовать mongodump против отключенного набора реплик.

Общие задачи

Если для вас действительно важен момент времени, убедитесь, что все часы ОСимеют одинаковое синхронизированное время и часовой пояс.Если вам нужно выполнить такую ​​синхронизацию, вы должны перезапустить mysqld и mongod.Затем ваши задания в crontab для mysqldump и mongodump завершатся одновременно.Лично я бы задержал mongodump примерно на 30 секунд, чтобы убедиться, что идентификаторы из mysql, которые вы хотите опубликовать в MongoDB, учтены.

Если у вас mysqld и mongod, запущенные на одном сервере, то вам не нужен MongoDBрепликация.Просто запустите mysqldump в 00:00:00 (полночь), а mongodump в 00:30:00 (30 секунд после полуночи).

2 голосов
/ 08 марта 2012

Я не думаю, что есть простой способ сделать это.Mongo не имеет сложных транзакций с поддержкой отката, поэтому очень сложно поддерживать такую ​​целостность.Один из способов решения этой проблемы - думать о нем как о двух бухгалтерских книгах, записывать все обновления в бухгалтерской книге mysql и затем воспроизводить их в бухгалтерской книге Монго для поддержания целостности.Другое возможное решение - сделать это на уровне приложения и остановить запись.

0 голосов
/ 26 марта 2012

Там действительно нет способа сделать это без какой-либо внешней проверки или принуждения.

Если вам действительно необходимо обеспечить идеальную целостность между ними, один из способов сделать это - использовать временные метки как для данных MySQL (все записи), так и для записей Монго, а затем создать резервную копию каждой из них, отфильтрованной по временным меткам, используя инструменты для каждая для выбора только тех записей, которые существуют непосредственно перед запланированным резервным копированием (см. http://www.electrictoolbox.com/mysqldump-selectively-dump-data/, чтобы узнать, как использовать mysqldump с предложением WHERE и http://www.mongodb.org/display/DOCS/Import+Export+Tools#ImportExportTools-mongodump, чтобы вывести коллекцию MongoDB с запросом)

В зависимости от того, как вы на самом деле используете каждое из ваших хранилищ данных, вы можете сделать что-то еще ... Например, если вы пишете только в свою MongoDB и никогда не обновляете и не удаляете, тогда было бы разумно сделайте резервную копию вашей базы данных MySQL, затем сделайте резервную копию вашей MongoDB (которая теперь может иметь некоторые дополнительные записи, потому что она резервируется впоследствии), а затем удалите записи MongoDB, которые не соответствуют чему-либо в MySQL. Как я уже сказал, это зависит от того, как вы их используете.

Но метка времени будет работать независимо - у вас просто есть дополнительные издержки на метки времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...