Есть ли лучший выход из журнала MySQL InnoDB «в будущем»?

16

Я получил эту ошибку InnoDB в MySQL 5.0. Mysqld был остановлен чисто, но мне удалось потерять ib_logfile0 & ib_logfile1 впоследствии. Теперь, после чистого запуска, InnoDB сделал свое «восстановление после сбоя». Я просмотрел бизнес innodb_force_recovery = 4, отремонтировал зависшую таблицу MyISAM, и теперь репликация готова, кроме этого. Большие числа переданы:

111116 15:49:36  InnoDB: Error: page 393457 log sequence number 111 561,760,232
InnoDB: is in the future! Current system log sequence number 70 3,946,969,851.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

Это на подчиненном сервере. Выше ошибка извергает сотнями. Я нашел ответ: «вставьте и удалите данные размером> 64 ГБ, чтобы порядковый номер журнала стал достаточно большим».

http://forums.mysql.com/read.php?22,50163,50163#msg-50163

Это магическое число 64 ГБ прибывает из 4 ГБ * 16, где «основной номер» журнала этого парня должен был увеличиться с 0 до 15. У меня с 70 до 111 = 164 ГБ. Это займет 5 дней. Я продолжу работать над ускорением моего сценария и буду запускать его параллельно, чтобы ускорить это. В то же время, я надеюсь, что у кого-то есть лучший ответ. Это глупо.

IcarusNM
источник
Один многообещающий ответ: «Если это подчиненный сервер, лучшим решением было бы отодвинуть базу данных в сторону и установить новый снимок с главного устройства». К сожалению, 20 000 таблиц в 25 базах данных, сочетание MyISAM и InnoDB, работают круглосуточно. Это займет слишком много времени, чтобы закрыть все это и выполнить новую полную репликацию, прежде чем снова запустить репликацию.
IcarusNM
4
Теперь эта 8-ядерная машина стоит на коленях в бессмысленной гонке за созданием и удалением 164 гигабайт данных. Единственная альтернатива, которую я слышу, состоит в том, чтобы уничтожить все на этом рабе и начать все заново. Все для эффективного изменения одного номера в двух файлах. Конечно, есть какой-то инженер InnoDB с профессиональным советом. Кто-нибудь когда-нибудь открывал ib_logfile0 в Emacs, нашел магическое число в гексе и просто изменил его?
IcarusNM
Вот отличная статья о нескольких способах сделать это. Percona определенно является авторитетом в MySQL. percona.com/blog/2013/09/11/…
jbrahy

Ответы:

10

Это была довольно редкая ситуация. Я надеюсь никогда не оказаться там снова, с InnoDB "порядковый номер журнала в будущем!" ошибка. Из-за моих конкретных деталей перестройка / восстановление данных моего сервера была последним средством. Некоторые читы в помощь были хорошими идеями, но, в конце концов, я решил просто улучшать свой Perl-скрипт, чтобы играть в эту глупую игру и набирать как можно больше концертов в час. Какого черта, это хороший системный стресс-тест.

Помните: цель состоит в том, чтобы увеличить один счетчик («порядковый номер журнала»), который хранится где-то в заголовках ib_logfile0 и ib_logfile1 . Это для того, чтобы подделать InnoDB, чтобы он игнорировал явный временной сдвиг и продолжал жить. Но никто не знает, как редактировать этот номер. Или, если они знают, никто не говорит.

Вот мой конечный продукт. YMMV, но использование функции REPEAT в mysql для внутренней генерации данных очень эффективно.

 #!/usr/bin/perl
 use DBI;
 $table = shift || die;
 $dbh = DBI->connect("DBI:mysql:junk:host=localhost", "user", "pass"); #Edit "junk" (DB name), user, and pass to suit.
 $dbh->do("DROP TABLE IF EXISTS $table");
 $dbh->do("CREATE TABLE $table (str TEXT) ENGINE=INNODB");
 $sth = $dbh->prepare("INSERT INTO $table (str) VALUES (REPEAT(?,1000000))");
 foreach (1..50) {
    $sth->execute('0123456789');   # 10 MB
 }
 $dbh->do("DELETE FROM $table");

Мой предложенный рецепт:

  1. Создать «мусорную» базу данных
  2. Сохраните выше PERL скрипт как junk.pl .
  3. Запустите junk.pl data1 , junk.pl data2 , junk.pl data3 и т. Д. Одновременно , чтобы запустить столько процессорных ядер, сколько у вашего сервера баз данных. Откройте несколько снарядов и завернуть каждый проход цикла Bash: while true; do date; junk.pl dataX; done.

Наблюдайте, как растет ваш LSN, возможно, в другом цикле:

 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 3871092821
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 4209892586
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 125 85212387

Большим числом является 32-разрядный INT без знака, который будет иметь размер 4 ГБ, увеличивая меньшее число каждый раз. В приведенном выше случае он просто опустился со 124 до 125. Ваша цель скрыта в mysqld.log, который отправил вас в Google за это нелепое решение. Как только вы пересечете финишную черту, все! Дуй в рога! Выпустите конфетти!

Боковая панель: это обнаружило интересную ошибку в mysqld 5.0 с REPEAT: если вы перейдете на 20 МБ, он перевернет внутренний счетчик и переместится на ~ 96 КБ. Нет предупреждений или ошибок нигде. Я не собирался тратить время на это. 10 МБ работает отлично. Если вы достигнете какого-то другого предела, он может пожаловаться. У меня есть различные буферы innodb, увеличенные по умолчанию. Сезон по вкусу. Как всегда, смотрите mysqld.log в одном окне.

IcarusNM
источник
Проверьте это percona.com/blog/2013/09/11/…
Джонас Стенсвед
Спасибо Джонас; Это интересно. Я думаю, что могу придерживаться моего метода выше. Он показывает использование gdb против запущенного mysqld, которым я бы никогда не рискнул. Но хорошей информации там тоже нет.
IcarusNM
По какой-то странной причине, используя MariaDB, я не получаю порядковые номера журнала «маленькое число [пробел] большое число», а просто «большое число», поэтому, к сожалению, этот метод не работает для меня. Ну, конечно, журнал обновляется, я просто не знаю, когда остановиться!
Гвинет Ллевелин
5

У вас есть три (3) варианта:

ВАРИАНТ 01: Выполнить rsync от Master до Slave (время простоя на Master)

  • Шаг 01: Запустите reset master;мастер (Zaps Binary Logs)
  • Шаг 02: service mysql stopна мастере
  • Шаг 03: service mysql stopна раб
  • Шаг 04: rsync / var / lib / mysql от ведущего к подчиненному
  • Шаг 05: service mysql startна мастере
  • Шаг 06: Используйте первый двоичный журнал на главном сервере как журнал, с которого начинается репликация. Используйте размер файла этого журнала в качестве позиции для запуска репликации с
  • Шаг 07: service mysql stop --skip-slave-startна раб
  • Шаг 08: Запустите команду CHANGE MASTER TO, чтобы настроить репликацию из журнала и положение, определенное на шаге 06
  • Шаг 09: Запустите start slave;на ведомом устройстве и дайте репликации догнать

ВАРИАНТ 02: Выполнить rsync от Master до Slave (минимальное время простоя на Master)

  • Шаг 01: Запустите reset master;мастер (Zaps Binary Logs)
  • Шаг 02: service mysql stopна раб
  • Шаг 03: rsync / var / lib / mysql от ведущего к подчиненному
  • Шаг 04: повторяйте шаг 03, пока два последовательных rsyncs не займут одинаковое количество времени
  • Шаг 05: service mysql stopна мастере
  • Шаг 06: rsync / var / lib / mysql от ведущего к подчиненному
  • Шаг 07: service mysql startна мастере
  • Шаг 08: Используйте первый двоичный журнал на главном сервере как журнал, с которого начинается репликация. Используйте размер файла этого журнала в качестве позиции для запуска репликации с
  • Шаг 09: service mysql stop --skip-slave-startна раб
  • Шаг 10: Запустите команду CHANGE MASTER TO, чтобы настроить репликацию из журнала и положение, определенное на шаге 08
  • Шаг 11: Запустите start slave;на ведомом устройстве и дайте репликации наверстать упущенное

ВАРИАНТ 03: Используйте XtraBackup

Этот программный инструмент не только сделает ненавязчивую копию работающего мастера, но и создаст для вас соответствующие файлы ib_logfiles. Вам придется настроить репликацию

Я уже писал в StackExchange на эту тему

Я делал это много раз для моей веб-хостинговой компании. У одного клиента было 3,7 ТБ для перемещения, и это заняло около 16 часов. 64ГБ очень мало по сравнению.

RolandoMySQLDBA
источник
В ОПЦИИ 02 Шаг 05 вы говорите, чтобы запустить мастер. Когда это было остановлено? Rsync на живом мастере - это мужество. Я впечатлен. И, к счастью, я использую innodb_file_per_table. Но в конечном итоге вам нужно прикусить пулю и остановить мастер достаточно долго, чтобы запустить один финальный rsync перед началом репликации. Я могу прибегнуть к такой возможности, но это очень активная СУБД. И я посмотрю на XtraBackup для моей информации.
IcarusNM
@IcarusNM: Ах, опечатка. Я исправил это. Спасибо !!!
RolandoMySQLDBA
ВАРИАНТ 02, вероятно, все еще может использовать некоторую работу. Например, вы должны выполнить шаг 2 до шага 1. Возможно, вы хотите, чтобы где-то там был RESET SLAVE. Опечатка в шаге 4. И вы говорите «первый двоичный журнал» в шаге 5, но вы действительно имеете в виду «только» или «последний» двоичный журнал. И вы должны использовать mysqlbinlog, чтобы определить позиции журнала, а не размер файла. И все это все равно не сработает, если вы не остановите мастера в какой-то момент. Основывать позицию / время записи в журнале, когда rsync завершил, в лучшем случае рискованно.
IcarusNM
В течение последних 4 лет я выполнял ВАРИАНТ 2 с клиентами хостинга БД, у которых есть данные в диапазоне TeraByte. Он работает каждый раз на работающем сервере. Единственная настоящая ошибка, которую вы можете совершить, - это раб. Эта ошибка заключается в том, правильно ли настроена репликация или нет. Кроме того, RESET SLAVEэто полезно, особенно если вы накопили много ГБ журналов ретрансляции. После процесса rsync и восстановления репликации помните, что команда CHANGE MASTER TO также уничтожит журналы ретрансляции для вас.
RolandoMySQLDBA
ммм ... странно. я настроил своего ведомого с помощью xtrabackup (как всегда) и все еще получил эти ошибки журнала (percona mysql 5.5.x) ... кажется, что на этом ведомом устройстве что-то пошло не так, и я должен сделать это снова.
harald
2

Я обнаружил, что, возможно, есть более крутой способ решения этой проблемы, работающий с многораздельными таблицами. Мне нужно было удалить разделы несколько лет назад, и мне пришлось добавить несколько на 2014 год. Почти все разделы сообщают об этой ошибке, также как и старые. Очень неприятный сбой.

Таким образом, в то время как УДАЛЕНИЕ старого и использование REORGANIZE раздела MAXVALUE (последнего), он будет создавать новые файлы, которые в порядке, поэтому я получаю все меньше и меньше предупреждений. В то же время, это помогает увеличить счетчик последовательности журнала, поэтому мне не нужно вставлять фиктивные данные. У меня это происходит на главном сервере, кстати ...

Итак, это:

ALTER TABLE Events DROP PARTITION p1530 , p1535 , p1540 , p1545 , 
p1550, p1555 , p1560 , p1565 , p1570 , p1575 , p1580 , p1585 , p1590 , 
p1595 , p1600 , p1605 , p1610 , p1615 , p1620 , p1625 , p1630 , p1635 , 
p1640 , p1645 , p1650 , p1655 , p1660 , p1665 , p1670 , p1675 , p1680 , 
p1685 , p1690 , p1695 , p1700 , p1705 , p1710 , p1715 , p1720 , p1725 , 
p1730 , p1735 , p1740 , p1745 , p1750 , p1755 , p1760 , p1765 , p1770 , 
p1775 , p1780 , p1785 , p1790 , p1795 , p1800 , p1805 , p1810 , p1815 , 
p1820 , p1825 , p1830 , p1835 , p1840;

И это:

ALTER table Events REORGANIZE PARTITION p3000 INTO (
PARTITION p3500 VALUES LESS THAN (TO_DAYS('2013-01-01')),
PARTITION p3510 VALUES LESS THAN (TO_DAYS('2013-01-04')),
PARTITION p3520 VALUES LESS THAN (TO_DAYS('2013-01-07')),
PARTITION p3530 VALUES LESS THAN (TO_DAYS('2013-01-10'))
...
PARTITION p4740 VALUES LESS THAN (TO_DAYS('2014-01-08')),
PARTITION p9000 VALUES LESS THAN MAXVALUE)

Это эффективно отбросит каждый раздел в изменении и воссоздает его с временной копией содержимого того, что было там. Вы можете сделать это для каждой таблицы, если хотите, мое приложение позволяет это делать, поэтому не нужно беспокоиться о синхронизированных резервных копиях и т. Д.

Теперь для остальной части таблицы, так как я не коснулся всех разделов в процессе, некоторые останутся с предупреждением о последовательности журналов, для тех, которые сломаны, но и покрыты этим действием реорганизации, я, вероятно, выполню это:

ALTER TABLE Events REBUILD PARTITION p0, p1;

или это

ALTER TABLE Events OPTIMIZE PARTITION p0, p1;

Итак, это заставило меня задуматься: вы можете сделать это с простыми ванильными таблицами, временно добавить разделы с помощью хэша, а затем удалить его (или оставить их, я настоятельно рекомендую разделы).

Однако я использую mariadb, а не mysql (поэтому XtraDB)

Возможно, это кому-то поможет. Я все еще бегаю, пока все хорошо. Смена ENGINE, похоже, тоже хорошо справляется с этой задачей, поэтому я перенесу ее обратно между MyIsam и ими обратно в InnoDB.

Это довольно логично, если вы измените ENGINE, таблица исчезнет из innodb, так что это больше не будет проблемой.

ALTER TABLE Events ENGINE=MyISAM;
ALTER TABLE Events ENGINE=InnoDB;

это похоже на работу здесь. Я могу подтвердить несколько вещей на секционированных таблицах:

  • ALTER TABLE xyz ENGINE = InnoDB очень медленный, в Aria (mariadb) в два раза быстрее, но в целом медленный способ увеличить счетчик лог-последовательности
  • ALTER TABLE xyz REBUILD PARTITION ALL - это самый быстрый способ «исправить» таблицы и помочь увеличить счетчик
  • ALTER TABLE xyz ANALYZE PARTITION ALL медленно сравнивается с первым и не переписывает разделы, которые подтвердили, что все в порядке. REBUILD обеспечивает перезапись схемы временной таблицы.

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

обновление : я могу сделать несколько выводов, теперь мне удалось решить эту проблему.

  • Мой сбой был вызван реорганизацией разделов таблицы в формате Aria (MariaDB).
  • (для меня) перестройка разделов работала лучше и быстрее, чтобы получить счетчик последовательности. Изменение двигателя происходит медленно, и вам нужно сделать это дважды, чтобы повлиять на innodb. изменение innoDB происходит довольно медленно по сравнению с MyIsam или Aria.
  • Я обновил до MariaDB 5.3, а не до 5.5 (был: 5.2), и он работает нормально. Я думаю, что слишком много проблем с aria, разделами в 5.5 (и подтвержденными ошибками), чтобы использовать эту комбинацию.
  • Там действительно должен быть лучший способ сбросить счетчик последовательности журнала.
Гленн Плас
источник
В MariaDB вы можете быстро изменить все таблицы с помощью USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(source: dba.stackexchange.com/questions/35073/… ) и передать его в файл, который будет выполнен в виде последовательности команд.
Гвинет Ллевелин