відновити єдину базу даних mysql в зайнятій реплікуваній системі master-slave


10

Шукайте стратегію чи інструмент для відновлення єдиної бази даних до моменту часу у зайнятій реплікаційній системі.

У мене 12 баз даних, що працюють на 2 серверах MySQL 5.0.77 в конфігурації головного підлеглого. Щоденний домен використовується щоденно тільки для читання, і є додаткові скиди SQL, за допомогою яких створюються резервні копії поза сайтом, а стан реплікації контролюється.

Редагувати: таблиці є сумішшю InnoDB та myISAM, тому конкретні рішення щодо двигуна не доступні.

Отже, зважаючи на повний збій головного сервера, я можу порушити реплікацію та просувати підлеглий сервер, у мене також є можливість відновити новий сервер і налаштувати з офсайду ПОВНУ резервну копію, а потім застосувати диференціали, що приймаються щоденно від веденого.

Однак мене турбує, як боротися з частковим збоєм або збоєм єдиної бази даних. Я можу придумати два сценарії, які цілком вірогідні;

  1. база даних 7 (наприклад) стає пошкодженою, продовжує обслуговувати деякі запити, поки хтось не помітить, що вона порушена, або попередить файли журналу ...
  2. Деякі запити, такі як база даних "drop", таблиця "drop", "оновлення де ...", - це запит, який містить одну базу даних або деякий підмножина.

На даний момент у мене є купа FULL демпфірованих файлів як FULL- $ DATE-all-databases.sql.gz файлів та диференціалів, які можна застосувати до FULL сміттєзвалищ як DIFF- $ DATE-all-databases.sql.gz

Щоб відновити базу даних 7 до певного моменту, знадобиться переглядати файли FULL та DIFF та вручну застосувати цей sql.

Як мені діяти, щоб зробити можливість відновити один з попередніх скидів DIFF до головної бази даних?

Чи потрібно мені робити резервну копію на окремі файли бази даних, тобто

mysqldump --databases "database1" | gzip > database1.sql.gz
mysqldump --databases "database2" | gzip > database2.sql.gz
mysqldump --databases "database3" | gzip > database3.sql.gz

а не ..

mysqldump --master-data --lock--all-databases --all-databases | gzip > all-databases.sql.gz

Якщо я переходжу до окремих файлів mysqldump, що відбувається з двійковим журналом головних даних, і чи потрібно я навіть встановлювати --master-data для дампів відновлення головного сервера?

Відповіді:


7

Якщо у всій вашій базі даних використовується тільки InnoDB, у мене є хороші новини.

Вам слід паралельно скидати всю базу даних з підлеглого.

Насправді, ви можете змусити всі бази даних в один і той же час.

Перше, що потрібно пам’ятати про підлеглого - це те, що не потрібно вмикати бінарний журнал, якщо він не є головним для інших рабів.

Ви не можете використовувати --master-dataпараметр для паралельних скидів, оскільки кожен дамп матиме інше положення, записане у рядку 22 кожного файлу дампа. Краще записати останній файл журналу Master і розмістити підлеглий, виконаний за допомогою SHOW SLAVE STATUS\G. Таким чином, всі бази даних мають однакове місце в часі.

Ви можете збирати всі бази даних і сценарій паралельного скиду всієї бази даних.

DBLIST=/tmp/ListOfDatabasesToParallelDump.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema')" > ${DBLIST}

for DB in `cat ${DBLIST}` 
do 
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz & 
done 
wait 

mysql -h... -u... -p... -e"START SLAVE;"

Якщо баз даних просто занадто багато, скидайте їх 10 або 20 одночасно, як описано нижче:

DBLIST=/tmp/ListOfDatabasesToParallelDump.txt
SSS=/tmp/ShowSlaveStatusDisplay.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema')" > ${DBLIST}

COMMIT_LIMIT=20
COMMIT_COUNT=0    
for DB in `cat ${DBLIST}` 
do 
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz & 
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done 
wait 
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

mysql -h... -u... -p... -e"START SLAVE;"

Якщо вам потрібно відновити одну таблицю, ви можете паралельно скидати таблиці 20 за порядком розміру.

Спробуйте це:

TBLIST=/tmp/ListOfTablesToParallelDump.txt
SSS=/tmp/ShowSlaveStatusDisplay.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY data_length" > ${DBLIST}

COMMIT_LIMIT=20
COMMIT_COUNT=0    
for DBTB in `cat ${TBLIST}` 
do
    DB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $2}'`
    DUMPFILE=$DB-{DB}-TBL-${TB}.sql.gz
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} ${TB} | gzip >  ${DUMPFILE} & 
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done 
wait 
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

mysql -h... -u... -p... -e"START SLAVE;"

Тепер, коли у вас є сценарії для скидання баз даних або окремих таблиць, ви можете завантажити ці дані на свій розсуд. Якщо вам потрібно, щоб SQL виконувався з двійкових журналів на майстрі, ви можете використовувати його mysqlbinlogта надавати йому положення про час і виводити SQL в інші текстові файли. Вам просто потрібно провести ретельну перевірку, щоб знайти обсяг даних, які вам потрібні, незалежно від часових позначок, які мають журнали. Пам'ятайте лише, що часова мітка кожного двійкового журналу в ОС відображає останній раз, коли він був написаний.


блискучі відповіді подяки. Я думаю, що раб, доступний лише для читання на xfs, дає мені безліч варіантів, і ваші сценарії справді допомогли.
Том Н

за сценарієм, коли мені потрібно відновити масивний стіл для господаря з резервного копіювання з раба. Мені просто потрібно відновити таблицю на ведучому, і чи всі зміни повторюються на підлеглий, навіть якщо це 20 ГБ даних? Чи буде процес: 1) відключити ключі, 2) скинути таблицю на ведучий і підлеглий 3) відновити таблицю головного майстра 4) включити ключі --- і чи зможе майстер повторити всі 20 ГБ вниз на підлеглий?
Том Н

Якщо ці бази даних НЕ є innodb, чи можу я все-таки скинути їх паралельно?
Том Н

Так, якщо ви 1) заплануйте час простою, 2) запустіть service mysql restart --skip-networking, 3) виконайте паралельний дамп, 4) запустіть service mysql restart. Потім перезавантажте потрібні таблиці.
RolandoMySQLDBA

імовірно, якщо метою перезапуску було запобігти запису мережевих з'єднань у базу даних, я міг би досягти такого ж ефекту, використовуючи iptables i.e. iptables -I INPUT -p tcp --dport 3306 -j DROPeth0 і lo
Tom H
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.