Восстановление * секционированной * таблицы MySQL InnoDB из файлов ibd

Как я могу восстановить разделенную таблицу mysql InnoDB только из файлов .ibd в форме TableName # P # pname.ibd? Статья Криса Календаря здесь http://www.chriscalender.com/?p=28 работает для несекционированные таблицы с одним файлом .ibd, но шаги «отбросить» и «импорт» приводят к ошибке «механизм хранения не имеет этой опции» для многораздельных таблиц.

Уэс Смит в одном из комментариев по ссылке выше предлагает ручную процедуру для импорта одного раздела за раз, но у меня это не сработало. Если я попытаюсь последовать его подходу, создав несекционированную таблицу, переместив первый файл .ibd, переименованный в TableName.ibd, и выполнив импорт, импорт будет успешным, но в таблице будет ноль строк. Последующий предложенный шаг «добавить обратно в раздел», который я попробовал, поскольку "alter table TableName partition by range ... (partition pname1 values less than (...) ENGINE=InnoDB)"шокирующе заменяет файл TableName.ibd (соответствующий первому разделу) новым TableName # P # pname1.ibd тривиального размера. Я потерял данные на одном разделе, пытаясь это сделать. Мне нужно восстановить около 150 разделов.

Любые советы о том, как восстановить данные из файлов .ibd? Спасибо.


person Eva    schedule 02.09.2012    source источник


Ответы (1)


Итак, оказывается, что подход, предложенный в комментарии по ссылке в исходном посте, в конце концов работает. Удаление раздела, упомянутого в шаге «изменить таблицу ...» выше, было законным, поскольку он был намеренно удален в исходной таблице до потери файлов ibdata и журнала (но mysql все равно оставляет файлы .ibd не удаленными) . Процесс восстановления мучительно медленный, но мне удалось его написать, и я надеюсь, что он дойдет до завершения в течение следующих нескольких дней.

Вот несколько советов, если вы окажетесь в подобной ситуации, когда нужно восстановить много разделов. Предположим, у вас есть таблица TableName со 100 разделами. Обычно 100 разделов будут иметь последовательные идентификаторы innodb, если они были созданы с помощью оператора «create table», но в целом это может быть не так, поскольку разделы могли быть добавлены после создания. Итак, вот шаги:

1) Узнайте идентификатор innodb, соответствующий каждому разделу, используя метод календаря в блоге выше, как показано ниже. Обратите внимание, что этот шаг не требует перезапуска сервера mysql. Просто создайте таблицу типа TableName без каких-либо разделов и удалите ее табличное пространство. Затем переместите файл .ibd первого раздела (названный чем-то вроде TableName # P # pname1.ibd) в каталог базы данных как TableName.ibd и попробуйте импортировать его. Загляните в mysql error.log (обычно /var/log/mysql/error.log), чтобы узнать, какой у этого раздела innodb ID. Повторите этот шаг для каждого раздела (или по мере необходимости), пока у вас не будет двух кортежей (innodb_ID_i, partition_boundary_i) для всех разделов в файле.

2) Начните с пустого состояния innodb (остановите сервер, удалите ibdata и ib_logfile *, перезапустите сервер). Для каждой записи innodb_ID в файле на шаге 1 выше создайте таблицу TableName_i, например TableName. Например, если 100 разделов соответствуют идентификаторам 321, 322, ..., 370, 415, 416, ... 464 (два блока по 50 смежных идентификаторов в каждом), то напишите сценарий для создания 320 фиктивных таблиц, 50 таблиц. например TableName, 45 фиктивных таблиц и 50 таблиц, таких как TableName.

3) Для каждой таблицы TableName_i, созданной выше,

--do 

     (i) rename table TableName_i to TableName

     (ii) alter table TableName discard tablespace // important to do this step before the next one

     (iii) mv TableName#P#pname_i.ibd TableName.ibd // with the appropriate directory prefixes

     (iv) alter table TableName import tablespace

     (v) alter table partition by range (partition_field) (partition pname_i values less than (partition_boundary_i))   // This is the most and only time consuming step

     (vi) rename table TableName to TableName_i // or some other name or just dump it to a file

--repeat  

Обратите внимание, что все вышеперечисленные шаги являются сценариями и не требуют перезапуска сервера в любой момент, кроме начала шага 2, чтобы начать с пустого состояния innodb. Будьте внимательны, чтобы проверить успешность каждого подэтапа на шаге 3, прежде чем переходить к следующему, иначе последующие шаги могут завершиться неудачно и / или файлы .ibd могут быть перезаписаны. Если возможно, используйте копию на шаге 3 (iii) вместо mv.

Последнее замечание: может быть немного более простая альтернатива с использованием инструментария восстановления Percona с использованием шестнадцатеричного редактирования, но это не сработало для моего случая секционированных таблиц. Я столкнулся с той же, казалось бы, нерешенной проблемой с секционированными таблицами, как указано в одном из комментариев на http://www.mysqlperformanceblog.com/2011/05/13/connecting-orphaned-ibd-files/. Однако ваш пробег может отличаться. Если бы существовал способ избежать воссоздания разделов (как на шаге 3 (v) выше), это было бы очень быстро и быстро, но я не уверен, есть ли он.

person Eva    schedule 03.09.2012