Про Oracle, ASM, iSCSI и ядро 2.6.39-400
Date January 19th, 2015 Author Vitaly Agapov
Опять заметка про Oracle и опять в стиле "баги атакуют". Может, кому-нибудь пригодится. Итак, есть Oracle 11g, RAC (хоть это и не имеет значения) и группа дисков, получаемых по iSCSI и скормленных в ASM. Пока всё неплохо, но тут переходим к ключевому моменту: всё это работает на RHEL5 с UEK-ядром из ветки 2.6.39-400.
В какой-то момент становится понятно, что, если остановить iSCSI-таргет, с которого мы получаем диски, то, несмотря на normal redundancy и на наличие нескольких failgroups, инстанс ASM умирает, прихватывая с собой весь clusterware. Надёжность летит к чертям, кластер может упасть от любого чиха.
Вот что можно выяснить по горячим следам… После остановки таргета iSCSI-инициатор, который периодически шлёт туда NOP Out'ы (эдакие iSCSI-пинги), обнаруживает, что тот недоступен и стартует таймаут node.session.timeo.replacement_timeout из конфига, по истечении которых на все текущие IO-команды возвращает ошибку. ASM, получая эту ошибку, ругается. Если команда была на чтение, то просто ругается. Если на запись, то инстанс ASM останавливается и пытается перезапуститься.
По умолчанию replacement_timeout равен 120 секундам. Значение влияет только на то, насколько быстро ASM получит обратно ошибку и насколько быстро он упадёт. На время этого таймаута блочный scsi-девайс блокируется – в файле /sys/block/sdX/device/state будет состояние "blocked", то есть все IO-команды будут задерживаться и не возвращать никаких ответов. ASM и все запросы к представлениям v$asm… будут висеть.
Зато когда таймаут истечёт, IO-команды получат коды ошибок, а статус блочного девайса вернётся в "running". Диск в системе при этом видится как живой, хотя на самом деле его нет. Это показалось сначала каким-то стрёмным багом. Уверенность в этом усилилась, когда я проверил, как всё это работает в RHEL6 на 3.8-м ядре. Там как раз после таймаута девайс уходит в transport-offline, asm его тоже метит как оффлайн и все счастливы.
Но оказалось, что это не баг, а так и было задумано. Фича с оффлайном девайса оказалась в ядре только начиная с версии 3.6 (вот эти коммиты: раз и два), а значит во всех старых ядрах висящий в running'е блочный девайс с давно отвалившимся таргетом – это нормальное явление.
Но вернёмся к ASM. Через 120 секунд он получает ошибку, и в alert-логе инстанса ASM мы видим подобные строки:
01.
WARNING: Read Failed. group:1 disk:19 AU:0 offset:0 size:4096
02.
WARNING: Write Failed. group:1 disk:2 AU:1 offset:4096 size:4096
03.
ERROR: unrecoverable error ORA-15188 raised in ASM I/O path; terminating process 28246
04.
ERROR: unrecoverable error ORA-15188 raised in ASM I/O path; terminating process 21487
05.
PMON (ospid: 21449): terminating the instance due to error 493
06.
ORA-1092 : opitsk aborting process
07.
License high water mark = 52
08.
Instance terminated by PMON, pid = 21449
09.
USER (ospid: 31407): terminating the instance
10.
Instance terminated by USER, pid = 31407
11.
ERROR: -15(asmlib ASM:/opt/oracle/extapi/64/asm/orcl/1/libasm.so op ioerror error Invalid argument)
12.
ERROR: -15(asmlib ASM:/opt/oracle/extapi/64/asm/orcl/1/libasm.so op ioerror error Invalid argument)
А в kernel-логе вот такую примечательную строку, из которой мы можем узнать код ошибки SCSI:
1.
kernel: (31,6):asm_end_ioc:1152 ERROR: Invalid error of -67 on request 0xffff880c514a0440!
Поиск по MOS приводит к Bug 18438934 : INCORRECTLY SETTING A ASM_LOCAL_ERROR WHEN UNPLUGGING THE DISK. Из него мы узнаём, что в ядре 2.6.39.400 появились новые коды ошибок SCSI, которые драйвер ASM обрабатывать не умеет и поэтому генерит ASM_LOCAL_ERROR. Баг вроде как пофикшен в 2.6.39-400.215.9, но опыт показывает, что не совсем – падение таргета по-прежнему приводит к падению ASM-инстанса.
Поигравшись с ядром и поизучав код драйвера ASM в UEK-ядре, сделал такой вот патч для ядра 2.6.39-400.215.15.el5uek. На ядре с этим патчем ASM больше не глючит, нормально оффлайнит недоступные диски и не боится падений iSCSI-таргетов. Главной подсказкой был код ошибки 67 из kernel-лога, который в коде заменён макросом ENOLINK.
01.
# cat asm.nolink.patch
02.
diff -crBN a/drivers/block/oracleasm/driver.c b/drivers/block/oracleasm/driver.c
03.
*** a/drivers/block/oracleasm/driver.c 2015-01-16 08:52:13.000000000 +0300
04.
--- b/drivers/block/oracleasm/driver.c 2015-01-16 08:54:52.000000000 +0300
05.
***************
06.
*** 1165,1170 ****
07.
--- 1165,1171 ----
08.
case -EIO:
09.
case -ENODATA:
10.
case -EREMOTEIO:
11.
+ case -ENOLINK:
12.
r->r_error = ASM_ERR_IO;
13.
break;
14.
15.
***************
16.
*** 1172,1178 ****
17.
r->r_error = asm_integrity_error(r);
18.
break;
19.
20.
- case -ENOLINK:
21.
case -EBADE:
22.
case -ENODEV:
23.
r->r_error = ASM_ERR_NODEV;
24.
--- 1173,1178 ----
Tags: Linux, Oracle
Category:
Linux, Oracle |
No comments »