суббота, 17 февраля 2018 г.

Исправление Bad Primary Chunk ошибки в СУБД Informix при отсутствии backup

Иногда удаётся провести интересные
лабораторные исследования.
Был бы только свободен стенд.


Внештатная ситуация

Цель данной работы было разобраться с критической ситуацией, когда у нас происходит падение СУБД из-за аварии с системой хранения данных, в данной работе это был дисковый ресурс отдающийся по iSCSI, и у нас нет на руках бекапа. Эта ситуация, что нет бекапа, не должна возникать в промышленной эксплуатации СУБД, но в качестве лабораторной работы было интересно оказаться в ситуации когда есть: упавший сервер и нет копии БД.

Хочу предупредить сразу, что все действия описанные в данной статье совершаются на свой страх и риск и нет, абсолютно, ни какой гарантии, что данное описание является всего-лишь частным случаем конкретной ситуации.

Что произошло?
В момент работы сервера СУБД отпадает подключенный по iSCSI диск, причем пропадает он не сразу весь. И при последующем подъёме СУБД успевает пометить ... отдельное табличное пространство с физическим журналом, как отключенное и упасть уже окончательно. Обычно, проводимые тесты с системами хранения данных на FC, SAS подключаемые к серверу через HBA давали положительные результаты восстановления, т.к. сервер просто провисал и ничего не успевал записать о состоянии своего дискового пространства. Тут — успел. Значит будем разбираться с последствиями, и ещё раз напомню, что IBM в такой ситуации советует один правильный способ поведения — восстановление из сохраненной копии.

Описание ошибки или собираем анамнез

Здесь всё у нас относительно просто, жалобы стандартные — СУБД не стартует. Вообще и ни как. Всякие недокументированные команды, типа, oninit -r или oninit -PHY приводят к одному и тому же сообщению в online.log

08:56:38 Bad Primary Chunk '/opt/informix/lnk/chunk_physdbs'.
08:56:38 oninit: Fatal error in shared memory initialization

Данная ситуация должна пробить в холодной пот незадачливого админа, который считал, что backup делают только трусы. Но это лирика, тут есть только два варианта выбора дальнейших действий: либо вы решаете, что будете поднимать систему самостоятельно, либо обращаетесь в support IBM, хотя, ещё раз — единственный выход в такой ситуации это наличие резервной копии СУБД.

Здесь следует отметить момент, что сомневаться и решать вы можете до того как начнёте действовать, после того как приступите к восстановлению — не должно быть колебаний и сомнений. В любом случае вы уже имеете убитую БД.

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

oncheck -pr > oncheck_-pr.txt 
я специально предлагаю делать вывод этой команды в файл, что бы спокойно его проанализировать. Я не буду посвящать вас в описание вывода этой команды обращу лишь внимание, что нас интересует информация только по проблемному чанку, нас не интересует ни смещение записей журналов, ни текущие позиции – ничего лишнего. Смотрим наш вывод:

Chunk number           110 Flags                  0x30040 Chunk is online
Chunk path             /opt/informix/lnk/chunk_maindbs_14
Chunk offset           0 (p)
Chunk size             8388608 (p)
Number of free pages   6481134
DBspace number         109 
Chunk number           111
Flags                  0x32020 Chunk is offline
&                              Chunk is extendable
Chunk path             /opt/informix/lnk/chunk_physdbs
Chunk offset           0 (p)
Chunk size             33554432 (p)
Number of free pages   0
DBspace number         110
 
Chunk number           112
Flags                  0x30040 Chunk is online
Chunk path             /opt/informix/lnk/chunk_maindbs_15
Chunk offset           0 (p)
Chunk size             8388608 (p)
Number of free pages   3673348
DBspace number         111

Нас интересует Chunk number 111, я специально привёл его в окружении исправных чанков, это облегчит понятие ситуации в целом. 
В первую очередь обращаем внимание на Flags.
Мы видим, что исправный чанк, находящийся в Online, имеет 0x30040, в то время как проблемный чанк 111 установлен в 0x32020. Наше действие — попытаться перевести проблемный чанк с 0x32020 в 0x30040.

Да, я заранее знаю, что у меня в чанке /opt/informix/lnk/chunk_physdbs находятся корректные данные, а не смесь байтов из-за сбоя накопителя, откуда такая уверенность – не скажу, это практика и интуиция, а так же возможно ещё что-то.
Всё, анамнез собран — лечение назначено. Вперед!

Проводим реанимацию

Вначале немного из скучной теории.
В версии СУБД Informix 12.10 вся информация о состоянии чанков находится в корневом чанке (скажем так, это вроде как очевидно, но например, в той-же 5-й версии, да и в 7-й тоже – информация о чанке хранилась в самом чанке), в котором осуществляется первичная инициализация СУБД при установке. Речь идет несомненно о ROOTDBS. В пространстве ROOTDBS у нас при инициализации создаются служебные БД СУБД, содержится вся конфигурационная информация сервера, включая таблицу всех именованных пространств и соответствующие им чанки. Так же первично в это пространство у нас создаются журналы, как логический, так и физический, которые мы потом переносим в связи с рекомендациями от IBM. В данном случае нас интересовать будет информация о чанках и именованных пространствах с ними связанных. К сожалению, они не лежат все в одном месте, а "размазаны" по всему ROOTDBS, вперемешку с данными системных таблиц.
Но, следует обратить внимание на такой момент, что информация о чанке у нас прописывается в ROOTDBS три раза. Первый раз — это будет чисто определение типа пространства, а вот за этим определением, дальше в глубинах ROOTDBS встретятся ещё две записи отвечающие за установленное состояние флага интересующего нас чанка. Это важно, поэтому у нас должна быть не одна правка для проблемного чанка, а две.
Для начала сольём в файл чанк ROOTDBS:

dd bs=8192k if=/opt/informix/lnk/chunk_rootdbs of=chunk_rootdbs
Сделаем его копию chunk_rootdbs.edit для правки, хотя этот шаг не является обязательно необходимым, но лучше работать с копией.
Запускаем редактор hexeditor и запустив поиск по ^W ищем по типу 'search for text string' имя нашего проблемного чанка. В полученной HEX строке внимательно рассматриваем атрибуты похожие на проблемный флаг: 032020.

04249290 00 00 00 00 00 00 00 00 00 03 20 20 08 00 00 6E .......... ...n
042492A0 00 1F 2F 6F 70 74 2F 69 6E 66 6F 72 6D 69 78 2F ../opt/informix/
042492B0 6C 6E 6B 2F 63 68 75 6E 6B 5F 70 68 79 73 64 62 lnk/chunk_physdb
042492C0 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 s...............

Правим на флаг соотвествующий статусу Online:

04249290 00 00 00 00 00 00 00 00 00 03 00 40 08 00 00 6E ..........@...n
042492A0 00 1F 2F 6F 70 74 2F 69 6E 66 6F 72 6D 69 78 2F ../opt/informix/
042492B0 6C 6E 6B 2F 63 68 75 6E 6B 5F 70 68 79 73 64 62 lnk/chunk_physdb
042492C0 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 s...............


и сразу же ищем второе вхождение по проблеменому чанку:

04252A90 00 00 00 00 00 00 00 00 00 03 20 20 08 00 00 6E .......... ...n
04252AA0 00 1F 2F 6F 70 74 2F 69 6E 66 6F 72 6D 69 78 2F ../opt/informix/
04252AB0 6C 6E 6B 2F 63 68 75 6E 6B 5F 70 68 79 73 64 62 lnk/chunk_physdb
04252AC0 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 s...............


и правим его:

04252A90 00 00 00 00 00 00 00 00 00 03 00 40 08 00 00 6E ..........@...n
04252AA0 00 1F 2F 6F 70 74 2F 69 6E 66 6F 72 6D 69 78 2F ../opt/informix/
04252AB0 6C 6E 6B 2F 63 68 75 6E 6B 5F 70 68 79 73 64 62 lnk/chunk_physdb
04252AC0 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 s...............

Сохраняем правку через ^X.
Можем посмотреть разницу правки между "оригинальным" и исправленным чанком, именно поэтому я и предлагал выше сделать копию.

cmp -l chunk_rootdbs chunk_rootdbs.edit | awk '{printf "%08X %02X %02X\n", $1, strtonum(0$2), strtonum(0$3)}'

0424929B 20 00    ⬅ по адресу 0424929B заменили 20 на 00
0424929C 20 40    
 по адресу 0424929C заменили 20 на 40
04252A9B 20 00
04252A9C 20 40

Всё, можем пробовать залить этот правленный ROOTDBS на место сломанного, что и делаем:

dd bs=8192k if=chunk_rootdbs.edit of=/opt/informix/lnk/chunk_rootdbs
Теперь делаем ещё раз: 

oncheck -pr > oncheck_-pr.edit.txt
и видим совершенно позитивную картину:
Chunk number           110 Flags                  0x30040 Chunk is online
Chunk path             /opt/informix/lnk/chunk_maindbs_14
Chunk offset           0 (p)
Chunk size             8388608 (p)
Number of free pages   6481134
DBspace number         109 
Chunk number           111
Flags                  0x30040 Chunk is online
Chunk path             /opt/informix/lnk/chunk_physdbs
Chunk offset           0 (p)
Chunk size             33554432 (p)
Number of free pages   0
DBspace number         110

Запускаем теперь через oninit саму СУБД и наслаждаемся On-Line режимом. Анализируем вывод online.log и видим обычный подъём после падения. По-хорошему на этой стадии, надо пройти все базовые oncheck (обязательно):
  • oncheck -cc -n
  • oncheck -ce -n
  • oncheck -cR -n
И, крайне желательно, если у вас не отбирают сервер, выполнить долгие процедуры чека по каждой БД в СУБД, т.е. выполнить как минимум:
oncheck -cD -n
и как максимум:
oncheck -cI -n 
Если есть в этом необходимость, тут уже можно сделать и нормальный backup СУБД через, например, ontape. Хотя бы, что бы потом опять не "шаманить" с подъёмом.




Комментариев нет: