Чи є кращий вихід з журналу 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, де журнал innodb цього хлопця "основне число" потрібно було збільшити з 0 до 15. Моє значення збирається з 70 до 111 = 164 ГБ. Це займе 5 днів. Я продовжуватиму працювати над тим, щоб пришвидшити свій скрипт, і паралельно його виконувати, щоб прискорити це. Тим часом я сподіваюся, що хтось інший має кращу відповідь. Це нерозумно.


Одна багатообіцяюча відповідь: "Якщо це рабовласницький сервер, найкращим рішенням було б перенести базу даних убік та встановити новий знімок від майстра". На жаль, у виробництві 24х7 є 20 000 таблиць у 25 базах даних, це суміш MyISAM та InnoDB. Вимкнути все це буде потрібно занадто багато часу і зробити повну реплікацію, перш ніж запускати реплікацію знову.
ІкарNM

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 тощо, щоб почати стільки ядер CPU, скільки має сервер вашої бази даних. Відкрийте кілька снарядів і загорнути кожен прохід циклу 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, який надіслав вам в першу чергу Гуглінг за це смішне рішення. Як тільки ви перетнете цю фінішну лінію, це все! Удар роги! Відпустіть конфетті!

Бічна панель: у цьому виявлено цікаву помилку в mysqld 5,0 w / REPEAT: якщо ви перейдете до 20 Мб, вона перевертає деякий внутрішній лічильник і перекидається на ~ 96 Кб. Ніде ні попередження, ні помилки. Я не збирався витрачати час на це. 10 Мб працює чудово. Якщо ви дійдете до якоїсь іншої межі, вона може скаржитися. У мене різні буфери innodb, збільшені від замовчування. Приправити за смаком. Як завжди, дивіться mysqld.log в одному вікні.



Спасибі Йонас; це цікаво. Я думаю, що я можу дотримуватися свого методу вище. Він показує, що використовує gdb проти запущеного mysqld, який я, мабуть, ніколи не ризикнув. Але хороша інформація теж є.
IcarusNM

З якоїсь дивної причини, використовуючи MariaDB, я не отримую послідовних номерів журналу «невелике число [пробіл] велике число» - а лише «велике число», тому на жаль цей метод не працював для мене. Ну, звичайно, журнал оновлюється, я просто не знаю, коли зупинитись!
Гвінет Левелін

5

У вас є три (3) варіанти:

ВАРІАНТ 01: Виконайте rsync від Master to 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 to 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 Гб дуже мало в порівнянні.


В ВАРІАНТІ 02 Крок 05 Ви говорите запустити майстер. Коли це було зупинено? Rsync на живому майстрі - гуци. Я вражений. І на щастя, я використовую innodb_file_per_table. Але в кінцевому підсумку вам доведеться кусати кулю і зупинити майстра досить довго, щоб запустити одну остаточну rsync перед початком реплікації. Це можливо, до якого я можу вдатися, але це дуже активна СУБД. І я перегляну XtraBackup для моєї інформації.
IcarusNM

@IcarusNM: Ах, друкарня. Я це виправив. Дякую !!!
RolandoMySQLDBA

ВАРІАНТ 02, ймовірно, все ще може використовувати деяку роботу. Напр. Ви повинні зробити крок 2 перед кроком 1. Ви, мабуть, хочете, щоб десь там був RESET SLAVE. Введіть крок 4. І ви говорите "перший бінарний журнал" на кроці 5, але ви дійсно маєте на увазі "лише" або "останній" двійковий журнал. І вам слід використовувати mysqlbinlog для визначення позицій журналу, а не розміру файлу. І все це все одно не буде працювати, якщо ви не зупините господаря в якийсь момент. Встановлення положення / часу журналу, коли завершено rsync, в кращому випадку ризиковано.
IcarusNM

Я працював ВАРІАНТ 2 протягом останніх 4 років з клієнтами DB Hosting, які мають дані в діапазоні TeraByte. Він працює щоразу проти запущеного сервера. Єдина реальна помилка, яку ви могли зробити - це раб. Ця помилка була б у тому, правильно чи налаштована реплікація. Крім того, RESET SLAVEкорисно, особливо якщо ви накопичили багато ГБ журналів ретрансляцій. Після процесу rsync та відновлення реплікації, будь ласка, пам’ятайте, що команда CHANGE MASTER TO також знищить журнали ретрансляції для вас.
RolandoMySQLDBA

ммм ... дивно. я налаштував мого раба за допомогою xtrabackup (як завжди), і все-таки отримав ці помилки журналу (percona mysql 5.5.x) ... здається, на цьому рабі щось пішло не так, і мені доведеться це зробити ще раз.
Харальд

2

Я з'ясував, що існує, мабуть, крутіший спосіб вирішити цю проблему, працюючи над розділеними таблицями. Мені потрібно було скинути розділи з декількох років тому, і довелося додати їх за 2014 рік. Практично всі розділи повідомляють про цю помилку, як і старі. Дуже неприємна аварія.

Тож, ВІДКРИТИ старий і використовуючи REORGANIZE розділу MAXVALUE (останній), він створить нові файли, які є в порядку, тому я отримую все менше і менше попереджень. Тим часом це допомагає збільшити лічильник послідовностей журналів, тому мені не потрібно вставляти помилкові дані. У мене це відбувається на головному сервері btw ...

Отже це:

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. зміна на INTERND є досить повільною порівняно з MyIsam або Aria.
  • Я перейшов до MariaDB 5.3, а не до 5.5 (було: 5.2), і він працює чудово. Я думаю, що існує занадто багато проблем з арією, розділами в 5.5 (і підтвердженими помилками), щоб використовувати цю комбінацію.
  • Справді повинен бути кращий спосіб скинути лічильник послідовностей журналів.

У програмі MariaDB ви можете швидко змінити всі таблиці за допомогою USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(джерело: dba.stackexchange.com/questions/35073/… ) і відредагувати його у файл, який буде виконуватися у вигляді серії команд.
Гвінет Левелін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.