pondělí 22. října 2018

Následky plánované odstávky el. energie aneb co se může pokazit, to se pokazí ...

V naší budově bylo potřeba provést kompletní odstávku el. energie. Kompletní znamená, že jsou vypnuty i zálohované rozvody, které jsou napojené na UPS a diesel generátor. Taková akce je poměrně náročná na přípravu. Ačkoli máme primární produkční hardware pro naše hlavní systémy (ISKN, RÚIAN, ISÚI, VDP atd.) umístěn v housingu, tak přesto je v budově spousta další techniky, včetně záložního centra, pomocných serverů atd. Pro představu, je to několik desítek fyzických serverů (virtuály ani nepočítám), pár enterprise diskových polí, páskové knihovny, switche, firewally a spousta dalších zařízení.


Proces vypínání i zapínání není jednoduchý a obě části trvají vždy několik hodin. Je potřeba jednotlivé zařízení, včetně virtuálních, vypínat ve správném pořadí. Nemůžete např. vypnout diskové pole před vypnutím všech serverů, které jsou na něj napojeny atd. Existuje spousta závislostí, včetně závislostí mezi systémy a opravdu to není legrace. Nakonec se vypnou všechny jističe, i z důvodu zamezení špičky během zapínání. Zapíná se také postupně a je na to plán, jako na vypínání.

Při takové akci vždy něco, jak se lidově říká, odejde. Není to otázka zda, ale kolik. Většinou to odnese pár disků a zdrojů. Ovšem tentokrát se opravdu zadařilo. Mohlo nás už varovat, že ještě před odstávkou odešel disk v poli IBM Storwize V7000. Disk se vyměnil a těsně před započetím odstávky se stihl dopočítat. Uff.
IBM Storwize V7000

Vypínání 

Vlastní akce pak začala v pátek po 15:00 vypínací fází. Těsně po začátku volal technický pracovník budovy, který má na starost rozvody, našim administrátorům, zda může vypnout zálohované zásuvky v kancelářích. Byl ujištěn, že ani náhodou, protože z PC v kancelářích se kompletně řídí a provádí vypínání techniky. Za dalších 20 sekund napájení zásuvek vypnul... Tím se celé vypínání, za nadávání administrátorů, zkomplikovalo a protáhlo. Po vypnutí, včetně jističů, byly zahájeny nutné práce na el. rozvodech a po jejich dokončení, kolem 22:00, se začalo s druhou fází, zapínáním.


Zapínání 

Nebudu to moc protahovat a použiji slova kolegy, který celou akci řídil: "napájení bylo zapnuto před desátou a pak se začaly dít věci"

Nenastartovaly tři LAN switche (součást páteřních rozvodů budovy). Dva jsme postupně vyměnili za náhradní, porty z třetího se dočasně rozdělily do jiných switchů a bude nahrazen v pondělí.

Nenastartoval jeden z centrálních switchů. Po několika marných pokusech jsme to vzdali. Následně jsme to kolem čtvrté ráno zkusili znovu a switch nastartoval – hlásí ale critical chybu na supervisoru (řídící karta switche) a dále vadnou kartu 16x10Gbit. Ostatní karty momentálně fungují.

Nebylo funkční spojení mezi primární a záložní lokalitou (housingové centrum a naše budova v Kobylisích). Konzultací s technikem z Alef0 bylo zjištěno, že v obou DWDM (Dense Wavelength Division Multiplexing) v Kobylisích odešly stejné karty s optickým zesilovačem. Technik nabídnul zapůjčení jedné jejich karty ze skladu (ceníková cena cca 17 000 USD). Přivezl ji po půlnoci a kolem 01:00 bylo spojení lokalit obnoveno alespoň po jedné trase.
Pozn.: Druhou možností bylo, že v housingu vykrademe jedno z funkčních DWDM, abychom zprovoznili alespoň tu jednu trasu.

Nenastartovalo diskové pole IBM Storwize V7000. Do Kobylis přijel v noci technik z GC System a řešil to na místě s podporou IBM. Postupně se došlo k tomu, že velmi pravděpodobně během startu  pole zhavaroval jeden z disků tak nešťastně, že se rozhodila konfigurace řadičů. Podpoře IBM se  přes vzdálenou správu pole podařilo problém vyřešit a data byla zpřístupněna kolem 02:30. Vadný disk byl následně vyměněn.

Zhavaroval jeden z dvou zdrojů police s řadiči na diskovém poli HPE 3PAR. Náhradní zdroj byl objednán u HPE a dorazil v sobotu ráno kolem 08:00 a byl následně vyměněn.
HPE 3PAR
Ve dvou dalších serverech odešel disk, z toho u jednoho takovým způsobem, že byla poškozena data v celém mirroru a zřejmě bude nutná reinstalace.

U databázového serveru testovacích prostředí EPVDS došlo k poškození souborových systémů, naštěstí se to podařilo opravit.

U jednoho serveru v infrastruktuře DMS odešel zdroj.

Na centrálním firewallu došlo k poškození pravidel, byla nutná jejich úprava.
Pozn.: To zřejmě nebyl přímý následek vypnutí, spíše restartu, dále to zkoumáme.

Celou noc se bojovalo NAS clusterem, pravděpodobně nezvládnul věci kolem problémů s komunikací (a s nedostupnými některými síťovými porty u serverů v Kobylisích). Občas to znamenalo výpadek některých systémů a vyvrcholilo to kolem osmé totálním rozpadem NAS clusteru. Podařilo se ho zprovoznit, znamenalo to ale problémy v některých databázích (např. Nahlížení). Navíc, pravděpodobně z důvodu delší nedostupnosti druhého HPE 3PAR během odstávky, vyjmul Oracle clusterware voting disky mapované z tohoto pole tím pádem při každých problémech kolem NAS docházelo k restartu databází.

Databázaři si pak také užili své. Museli opravovat chybějící voting disky  a udělat rekonfiguraci všech disků datových skupin ASM, které jsou umístěny v záložní lokalitě a které byly po nastartování ve stavu missing apod.

Celá akce skončila v sobotu ráno kolem 09:00, kdy všechny systémy opět běžely. Z naší strany ji řídil Jirka V., kterému sekundovali Petr S., Karol J., Ondřej R., Tomáš R. a Martin D. a Jirka K. Patří jim velký dík, stejně jako GC System a Alef0 za noční spolupráci.


Závěr

Přemýšlím, jaké si z toho vzít ponaučení. To, že při vypínání, při našem množství techniky v budově, odejdou disky nebo zdroje, je už běžná věc a máme náhradní (nebo jsou redundantní). To, že sebou disk vezme celý RAID nebo znefunkční diskové pole už tak běžné není, ale i to se stane. Ale např. na to, že v obou DWDM  odejdou optické zesilovače, se prostě připravit nemůžete (mimo přípravy mít nasmlouvaný dobrý servis).

Kritickou infrastrukturu a produkční část systémů máme v housingu, ale i přesto je v budově velká spousta techniky, která tam už z principu být musí. Pohrávám si s myšlenkou, zda bychom naopak neměli vypínání dělat čestěji. Nikoli najednou, ale během celého roku, postupně, v kolečku, aby nebyly tak fatální následky. Možná by se tak podařilo odchytit načatý HW bez vážnějších dopadů. Možná by toho ale naopak díky častějšímu vypínání odešlo ještě více. Kdo ví...

pondělí 7. května 2018

Jak jsem hledat problém s uváznutím (deadlock) v aplikaci Návrh na vklad

ČÚZK vytvořil a provozuje www aplikací Návrh na vklad, která umožňuje uživatelů připravit formulář s návrhem na vklad do katastru nemovitostí. Její součástí jsou i webové služby, které pro generování návrhů využívají např. banky. Vývoj a provoz této aplikace mám na starost se svým týmem.

Při provozu jsme registrovali, že se občas vyskytuje chyba ORA-00060: deadlock detected while waiting for resource, což je problém s uváznutím, kdy se databázové transakce uzamknou proti sobě a ani jedna nemůže pokračovat dál.

Vytvořit deadlock je poměrně jednoduché. Stačí si otevřít dvě session a navodit například následující stav:
Krok Transakce 1 Transakce 2 Popis
    1 UPDATE platy SET plat=1000 WHERE zamestanec_id=1 Transakce 1 si v tabulce PLATY uzamkne záznam pro zaměstnance s ID 1
    2 UPDATE odmeny SET castka=2000 WHERE zamestanec_id=10 Transakce 2 si v tabulce ODMENY uzamkne záznam pro zaměstnance s ID 10
    3 UPDATE odmeny SET castka=500 WHERE zamestanec_id=10 Transakce 1 se pokouší v tabulce ODMENY uzamknout záznam pro zaměstnance s ID 10, což se ji nedaří, protože zámek drží transakce 2 a transakce 1 tedy musí čekat na dokončení transakce 2.
    4 UPDATE platy SET plat=300 WHERE zamestanec_id=1 Transakce 2 se pokouší v tabulce PLATY uzamknout záznam pro zaměstnance s ID 1, což se ji nedaří, protože zámek drží transakce 1 a transakce 2 tedy musí čekat na dokončení transakce 1.

V tento okamžik jsou obě transakce zacyklené. Transakce 1 čeká na dokončení transakce 2, ale ta zase čeká na dokončení transakce 1 a problém s uváznutím je na světě:

(obrázek z http://oracledbpro.blogspot.com/)

Oracle tento stav pomocí backgroud procesu DIAx detekuje, provede roolback příkazu, který ho způsobil a vyhlásí chybu ORA-00060: deadlock detected while waiting for resource.

Malá odbočka. Ohledně deadlocku v Oracle panuje několik mýtů, které je vhodné vyjasnit:
  • Oracle neprovede kill žádné session,
  • Oracle provede rollback příkazu, ale neprovede rollback celé transakce,
  • Oracle background proces PMON (Process Monitor) neuvolní předchozí zámky.
Deadlock se nemusí týkat jen řádků tabulce. Je to jeden ze synchronizačních problému a takto se může uzamknout prakticky cokoli. Hodně se to řeší v operačních systémech a je to velmi zajímavá problematika.

Zpět k naší aplikaci. Chyba ORA-00060 se nám občas vyskytovala v situaci, kdy uživatel, nebo automatický proces, mazal návrh na vklad. Vyskytovala se poměrně zřídka, ale časem začala narůstat na několik výskytů denně. 99 % bylo vyvoláno z automatického procesu, bez vlivu na uživatele, který chybu ani nepoznal.

Pokud se problém s deadlockem vyskytuje v aplikaci, tak je jeho příčina nejčastěji buď chyba v návrhu aplikace nebo chyba v datovém modelu. Většinou se špatně hledá.

Naše aplikace má jednoduchý datový model, který se skládá z cca 70 tabulek. Chyba se vyskytovala při mazání jedné z tabulek NEMOVITOSTI, STAVBY nebo PARCELY. Datový model této části vypadá zhruba takto:
část datového modelu


Při kontrole mazací procedury jsem nenarazil na problém, tak jsem se zaměřil na datový model. Ten jsem prošel, ale také mě nic do oka netrklo, tak jsem musel zkoumat dál. Oracle při výskytu chyby zapíše událost do alert logu (píši se zde všechny důležité události, která v databázi vznikly) a vytvoří trace soubor:
ukázka alert logu

ukázka trace (mívá jednotky až stovky MB)


Otevřel jsem trace a viděl, že problém v tomto případě vznikl při mazání záznamů z tabulky STAVBY:
mazané tabulky

Znovu jsem prověřil danou část modelu, ale vše vypadalo OK. Pátral jsem tedy dál. V trace je graf deadlocku:

Z něj jde vyčíst, že je problém v resource se jménem TM-003f719d-00000000 (viz (1)), kdy transakce má zámek typu SX a čeká na typ SSX. Zámek typu SX, na rozdíl od SSX, může získat pouze jedna transakce. Podle toho, že se nečekalo na uzamknutí řádků (viz (2)), bylo jasné, že se jednalo o problém přímo s uzamknutím celého databázovém objektu (tabulka, index, ...). Jak ho ale zjistit? 
Struktura jména resource TM-003f719d-00000000 mi nic neříkala a nedokázal jsem odvodit, z čeho je složena. Oracle má sice metadata o svých objektech, ale jsou to ID typu NUMBER (sloupec OBJECT_ID), takže tudy cesta nevedla:
pohled DBA_OBJECTS 

Po dalším pátrání na Oracle Metalinku se mi podařilo dohledat dokument Doc ID 62365.1, ve kterém se píše:
dokument Doc ID 62365.1

Takže TM je typ zámku a 003f719d je ID objektu, ale v HEX formátu (pozn.: také mě to mohlo napadnout :-) ). Převedl jsem tedy 003f719d do desítkové soustavy (4157853) a podíval se do metadat, kterému databázovému objektu patří:
identifikace objeku

Problém tedy vznikl při pokusu o uzamknutí tabulky PARCELY_PARCELY.  Při kontrola dalších trace se vždy jednalo pouze o tuto tabulku. Struktura tabulky je jednoduchá, její účel je pouze vazba mezi původními a nově vznikajícími parcelami. Má jen dva sloupce VZNIKAJICI_PARCELY_ID a PUVODNI_PARCELY_ID a oba se přes cizí klíče (FK) odkazují do tabulky PARCELY. Proč se ale zamykala celá? 
Podíval jsem se na indexy a bylo jasno. Tabulka měla sice složený index nad oběma sloupci, ale ne nad sloupcem PUVODNI_PARCELY_ID:
indexy na tabulce PARCELY_PARCELY

To je sice v pořádku pro logiku aplikace, protože se k tabulce vždy přistupuje i přes VZNIKAJICI_PARCELY_ID, ale problém vznikne, když se má mazat záznam v tabulce PARCELY (kde se maže i při mazání STAVBY nebo NEMOVITOSTI). Oracle se musí v ten okamžik podívat do tabulky PARCELY_PARCELY, zda tam nejsou záznamy, které by mazání bránily. Pokud se kontroluje obsah sloupce VZNIKAJICI_PARCELY_ID, tak použije index a je to OK. Ale pokud se kontroluje obsah sloupce PUVODNI_PARCELY_ID, tak se díky chybějícímu indexu uzamkne celá tabulka, což je problém. Aplikace sama o sobě index na tom sloupci nepotřebuje, ale Oracle už ano. 

Řešení bylo jednoduché - vytvoření nového indexu nad sloupcem PUVODNI_PARCELY_ID. Oracle tak při kontrole FK využije index, uzamkne pouze dané záznamy a nikoli celou tabulku. Tohle pracovníkovi při návrhu databáze nedošlo a bývá to poměrně častá chyba. Po vytvoření indexu chyba zmizela, jako mávnutím kouzelného proutku. Problém byl vyřešen a tím mé pátrání skončilo. 

Na závěr bych chtěl dodat, že by z toho mohl plynout závěr, že by se měl na každý sloupec, který obsahuje FK, udělat index a byl by pokoj. Mělo by tedy stačit zkontrolovat, např. jednoduchým dotazem do metadat Oracle, zda každý takový sloupec index má. To ale není dobrý přístup. Sice se vyhnete těmto problémům, ale budete nutit Oracle tento index udržovat, což stojí nějaké zdroje (disk, I/O, CPU). Je to třeba posuzovat případ od případu. Pokud se například odkazujete na číselníkovou položku, která se nemaže (číselníkové položky se typicky jen zneplatní), tak index potřeba není, protože tam žádná kontrola neprobíhá.