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

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

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

Ответ 1

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

Все ваши данные 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. Разрежьте на погоню. Вот как вы делаете script для преобразования всех ваших таблиц 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}

Просто запустите этот 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

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

Ответ 3

Нет никакого способа сделать это без какого-либо внешнего контроля или принудительного исполнения.

Если вам действительно нужно обеспечить идеальную целостность между двумя, один из способов сделать это - использовать временные метки для ваших данных mysql (все записи) и записи mongo, а затем создавать резервные копии каждого из них, отфильтрованных по меткам времени, используя инструменты для каждый из них выбирает только записи, существующие непосредственно перед запланированным резервным копированием (см. 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. Как я уже сказал, это зависит от того, как вы их используете.

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