У нас есть онлайн-система, использующая базу данных MySQL. Нам нужно объединить старую резервную копию базы данных (полные таблицы, а не файл дампа) с текущей. Как бы вы это сделали, не испытывая простоев сервера? Обратите внимание, что система работает круглосуточно и без выходных. Какие проблемы могут возникнуть?
Спасибо.
Когда вы возитесь с файловой системой MySQL, вы должны остановить сервер MySQL. Чтобы избежать простоя вашей действующей машины, используйте резервную / виртуализированную машину с ТАКОЙ ВЕРСИЕЙ сервера MySQL. В то время РЕЗЕРВНОЕ КОПИРОВАНИЕ Сервер MySQL остановлен, скопируйте таблицы (я предполагаю .FRM, .MYI и т.д.?) В файловую систему в / var / lib / mysql / BACKUP_DB (соответствующий каталог BACKUP_DB).
Начать РЕЗЕРВНОЕ КОПИРОВАНИЕ MySQL и убедитесь, что данные загружены правильно, используя сценарии или интерфейс командной строки. После проверки mysqldump база данных BACKUP_DB, чтобы ее можно было загрузить на рабочий сервер:
mysqldump --extended-insert BACKUP_DB > /root/sql/BACKUP_DB.sql
Теперь вы преобразовали необработанные данные резервного копирования в операторы SQL, которые можно загрузить в MySQL без простоя (в отличие от необработанных данных). Шаг BACKUP_DB.sql
к живой машине.
Импортировать BACKUP_DB.sql
в ваш ЖИТЬ Экземпляр MySQL как другая база данных:
mysql BACKUP_DB < /root/sql/BACKUP_DB.sql
Теперь у вас должна быть резервная база данных, загруженная в MySQL как BACKUP_DB.
Теперь, в зависимости от операторов INSERT IGNORE или REPLACE INTO (вы перезаписываете старые данные или «заполняете пробелы» в своих индексах?):
mysqldump --no-create-db
--no-create-info --extended-insert --insert-ignore MERGE_SOURCE | mysql BACKUP_DB
Или для действия ЗАМЕНИТЬ НА:
mysqldump --no-create-db --no-create-info --extended-insert MERGE_SOURCE | sed 's/INSERT INTO/REPLACE INTO/g' | mysql BACKUP_DB
В качестве альтернативы, вместо того, чтобы передавать выходные данные обратно в MySQL, отправьте их в файл и проверьте операторы SQL.
mysqldump --no-create-db --no-create-info --extended-insert --insert-ignore MERGE_SOURCE > /root/sql/merge.sql
mysqldump --no-create-db --no-create-info --extended-insert MERGE_SOURCE | sed 's/INSERT INTO/REPLACE INTO/g' > /root/sql/merge.sql
Наконец, чтобы избежать простоя, сбросьте первую базу данных вместо второй:
mysqldump BACKUP_DB | mysql CURRENT_DB
Вы всегда можете сначала заблокировать базу данных, чтобы предотвратить запись данных (например) в таблицу z с помощью внешнего ключа в таблице (которая уже была перезаписана):
FLUSH TABLES WITH READ LOCK;
(выполнить дамп, как на предыдущем шаге)
UNLOCK TABLES;
Добавьте команду FLUSH в начало файла дампа .sql и РАЗБЛОКИРОВАТЬ в конец.
Не забудьте четырехкратно проверить свои имена БД в этом сценарии! Задайте любой последующий вопрос, в котором вы не уверены, так как это очень рискованный метод смешивания данных. Выполните (и запишите подробно) точные шаги, необходимые на сервере разработки, если это возможно, или виртуализируйте свой тест, или создайте небольшой тест. Просто протестируйте. И, конечно же, сделайте достаточно резервных копий, чтобы покрыть любую возможную потерю данных.
В этом примере предположим, что ваша база данных называется «zig», а ваша резервная база данных называется «zig_backup». Я также предполагаю, что ваш база данных резервного копирования и ваша действующая база данных имеют одинаковую схему.
Я также предполагаю, что ваша действующая база данных постоянно обновляется, и вы не можете выполнить слияние «в автономном режиме», а затем щелкнуть переключатель, чтобы сделать объединенную копию «живой».
Следует помнить о следующих проблемах:
Процесс обновления потребует планирования того, какие таблицы объединить в первую очередь, а какие - в последнюю. Моя общая тенденция сначала делать тяжелую работу (большие столы), а затем переходить к меньшим столам. В зависимости от размера ваших данных это может не иметь значения.
Тогда процесс слияния будет следующим:
Самым безопасным методом было бы выполнить соединение всей таблицы и просто вставить строки, которые не совпадают:
for each table in the "live" database:
INSERT INTO zig.$table
SELECT BACKUP.* FROM zig_backup.$table AS BACKUP
LEFT OUTER JOIN zig.$table AS LIVE ON LIVE.ID=BACKUP.ID
WHERE LIVE.ID IS NULL;
Это, конечно, требует знания первичных ключей каждой таблицы. Прямое «ЗАМЕНИТЬ» может не сработать, поскольку строки в действующей базе данных могли измениться, и их измененные данные будут перезаписаны
Чтобы объединить недостающие таблицы, выполните:
\u zig_backup
SHOW TABLES
Чтобы получить список всех таблиц и определить, существует ли таблица в действующей базе данных, вы можете:
\u zig
SHOW TABLES LIKE 'tablename';
В качестве альтернативы, таблица в резервной базе данных, которая не существует в «живой» базе данных, может быть двоично скопирована в каталог действующей базы данных.
Наконец, обработка удалений из «живой» базы данных в лучшем случае затруднительна, тем более что из-за того, что вы выполняете слияние, некоторые данные отсутствуют по той или иной причине.
Настроить репликацию и переключить DB-сервер на подчиненный, когда он будет готов и хорошо протестирован (!!!).
Если у вас нет технических ограничений для этого, это единственный допустимый вариант (я имею в виду, что вы должны иметь возможность тестировать изменения, прежде чем вносить их в среду 24/7).
Предполагая, что у вас есть место на диске, я бы установил базу данных миграции и скопировал / слил в нее данные. Настройте копию своей веб-среды для подключения к базе данных миграции и тщательно протестируйте ее. Затем, когда вы будете довольны, измените строки подключения в производственной среде, чтобы посмотреть на новую базу данных миграции.
вы можете использовать опцию -T mysqldump, чтобы получить вывод таблиц в виде значений, разделенных табуляцией. Затем создайте копию живой БД как Кайл предлагает. Затем используйте mysqlimport, чтобы повторно импортировать данные в живую копию и протестировать ее там. Когда вы будете готовы перейти с живого на живую копию, вам понадобится некоторое время простоя.
Я сам не пробовал Пусть покупатель будет бдителен.