Окт. 292009
 

Днес за пръв път в живота си създадох релация с 395 атрибута. Не ме питайте в коя НФ е 🙂

При това не мога да я нарека „широка“, предвид „дължината“, която се очаква – няколко милиона кортежа дневно.

Това ако не е прасе…

 Posted by at 12:38

Не сме сами, част 3

 Общи  Коментарите са изключени за Не сме сами, част 3
Окт. 282009
 

(към част 2)

Един малко по-добър вариант изглежда така:

– В началото вземаме текущата дата
– Когато избираме кои данни да обработим, освен processed=0 гледаме и датата на зареждане – да е по-малка от датата за начало на обработката, която се запомнили
– когато изтриваме обработените данни от loader таблицата, отново изтриваме само тези, които са „заредени“ преди началото на обработката

Процедурата би изглеждала така:

create or replace procedure Process_New_Data2 is
  -- example code - has a BUG!!!
  transfer_date date;
begin
  -- get the time when we start the transfer
  transfer_date := sysdate;

  -- process the loaded batches
  insert /*+append*/
  into prod_table
    select -- do some processing
     batch_id, get_something(column1, column2), calculate_something(column3, column4),
     RANK() over(PARTITION BY column5, column6 order by column7) rn, 
     column8, column9, ...
      from loader_table
     where batch_id in (select batch_id
                          from batch_log
                         where load_time < transfer_date -- get only the batches loaded before we start
                           and processed = 0);

  -- delete the rows from loader table
  delete from loader_table
   where batch_id in (select batch_id
                        from batch_log
                       where load_time < transfer_date -- delete only the batches loaded before we start
                         and processed = 0);

  -- mark the batches as processed
  update batch_log
     set processed = 1
   where load_time < transfer_date -- mark only the batches loaded before we start
     and processed = 0;

  commit;
end;

За съжаление това отново не е гарантирано решение. Шанса за загуба на данни тук е много по-малък, но не е нулев, и много зависи от метода на зареждане на нови данни.

Проблема се изразявана едно ниво по-дълбоко: някоя сесия може да е заредила данни преди няколко секунди (може и минути), но да не е commit-нала промените. Съответно нашият inser-select няма да ги хване, но докато върви той, другата сесия има достатъчно време да направи commit и няколко милиона реда да се появят за малко, докато delete-а не ги изтрие безславно.

(към част 4)

 Posted by at 13:55

Не сме сами, част 2

 Общи  Коментарите са изключени за Не сме сами, част 2
Окт. 282009
 

(към част 1)

Дублирането на данни е много неприятно. То може да доведе до всякакви грешни резултати. Това, че се случва произволно, го направи и трудно за елиминиране (ако няма някакъв естествен ключ в данните). Така приходите на фирмата може да излязат 120 000, вместо 115 000. По-лошо: това може да се случи и с разходите 🙂

Но много по-тежка е ситуацията със загубата на данни. Това е в общи линии най-лошото, което може да се случи на една информационна система. Ако работи бавно – това се оправя (викате ме и ви казвам как 😉 ), ако не е удобна за потребителите – също, ако не си върши работата – доработва се. Но ако има загуба на данни, оправията е много по-трудна, понякога и невъзможна.

Ето и една весела процедура, която освен до дублиране, може до доведе и до загуба на данни:

create or replace procedure Process_New_Data is
  -- example code - has a BUG!!!
begin
  -- process the loaded batches
  insert /*+append*/
  into prod_table
    select -- do some processing
           batch_id, get_something(column1, column2), calculate_something(column3, column4),
           RANK() over(PARTITION BY column5, column6 order by column7) rn, 
           column8, column9, ...
      from loader_table
     where batch_id in (select batch_id
                          from batch_log
                         where processed = 0);

  -- delete the rows from loader table
  delete from loader_table
   where batch_id in (select batch_id
                        from batch_log
                       where processed = 0);

  -- mark the batches as processed
  update batch_log
     set processed = 1
   where processed = 0;

  commit;
end;

Тук забавлението настава така:
Сесия 1 прехвърля (много) данни с insert-select. Това, естествено, отнема време
Сесия 2 зарежда още един (или няколко няколко) batch в loader таблицата. Естествено, те са с processed = 0
Сесия 1 завършва с прехвърлянето и изтрива всички редове, които са били маркирани като не-прехвърлени (включително и новопостъпилите)

В този случай няма никакво значение къде ще сложите commit. И след всеки ред да има commit, пак няма да се избегне загубата на данни.

(към част 3)

 Posted by at 10:06

Не сме сами, част 1

 Общи  Коментарите са изключени за Не сме сами, част 1
Окт. 282009
 

(към част 0)

Първият пример е за система, в която постъпват данни от много места (асинхронно) и се правят се различни обработки (асинхронно). По всяко време някой процес може да извика дадена процедура и понякога това може да предизвика конфликти, които да доведат до дублиране (по-добрия вариант) или загуба на информация.

Ето примерна процедура, която води до дублиране на информация:

create or replace procedure Move_Some_Data is
  -- example code - has a BUG!!!
begin
  -- find all non-archived batches
  for batches in (select batch_id
                    from batch_log
                   where archived = 0) loop
    -- archive the current batch
    insert /*+append*/
    into arch_table
      select *
        from prod_table
       where batch_id = batches.batch_id;
  
    -- delete the rows from prod table
    delete from prod_table
     where batch_id = batches.batch_id;

  ... -- other tables containing batch information
  
    -- mark the batch as archived
    update batch_log
       set archived = 1
     where batch_id = batches.batch_id;
  
    -- finish the transaction
    commit;
  end loop;
end;

В този случай, ако по някаква грешка пуснем процедурата 2 пъти (почти) едновременно, има голяма шанс едни и същи данни да се случат в архива 2 пъти. Ето един интересен вариант:

– Сесия 1 изпълнява select заявката и получава курсор към не-архивираните batches 89, 90, 91 и 92. Започва цикъл за прехвърляне.
– Сесия 1 минава една итерация и прехвърля batch 89. Започва insert – select от втора итерация за batch 90
– Сесия 2 се включва в този момент. Изпълнява бързия select и получава курсор към не-архивираните (към този момент) batches 90, 91 и 92. Започва цикъл за прехвърляне.
– Сесия 2 също започва insert – select за прехвърляне на batch 90
– Сесия 1 завършва прехвърлянето на batch 90 и изтрива данните. Това не пречи по никакъв начин на сесия 2, защото тя получава consistent read копие на данните от преди изтриването
– Нататък може да стават всякакви произволни комбинации. Примерно ако данните в batch 91 са значително по-малко от тези в batch 90, сесия 1 може да ги прехвърли и изтрие преди сесия 2 да е свършила с първата си итерация. В този случай когато Сесия 2 стигне до втората си итерация, ще направи insert на 0 реда (и съответно delete), което би било много забавно за наблюдение ако има организиран log.

Елементарната защита в такъв случай би била вместо select да правим select for update на таблица batch_log. Това, в случая, не върши работа, защото (съвсем коректно), след всяка прехвърлена група записи се прави commit.

Едно по-добро решение ще предложа малко по-късно.

(към част 2)

 Posted by at 9:07
Окт. 282009
 

Преди 10 години, когато още бях програмист ( 😉 ), най-яката книга за мен беше Advanced Windows на Jeffrey Richter. Там се обясняват на дълго и на широко „вътрешностите“ на Windows от гледа точка на програмиране. Най-якото за мен беше multi-threaded програмирането и си умирах от кеф да правя някакви неща на много нишки.

При multi-threaded програмирането, основният проблем е синхронизацията между нишките. За да стане добре, програмиста трябва да може да мисли многонишково; да идентифицира критичните секции, евентуалните конфликтни места, и да ги защити. Основно правило е, че текущата нишка може да бъде прекъсната във всеки един момент, между всеки 2 инструкции, и ако работи с глобални данни, да настанат бели. Това важи и на ниво процес, но там има много по-голям шанс да ти се размине, защото обикновено ресурсите са ти доста локални. Да не задълбавам….

При многопотребителските БД имаме същото предизвикателство. За съжаление много програмисти не мислят за това. Някои мислят само за performance. Други и за това не мислят, но пак се отклонявам.

Ще се опитам да направя една серия, в която да покажа такива опасни практики. Честно казано, в момента не ми се занимава да пиша учебникарски примери за левашко управление на транзакции, макар че и такива съм виждал. Ще покажа варианти, които на пръв поглед изглеждат съвсем правилно написани (за нетренирано око). Ще използвам псевдо-код, написан на PL/SQL; но същите принципи важат и на Java, C#, Perl и кой да е друг език.

Между другото, коварното при такива бъгове е, че се проявяват много късно (когато системата се натовари с повечеко потребители). При „стандартно“ тестване всичко си минава – входните данни се преобразуват в изходни. Още по-коварно е, че се проявяват произволно във времето, сякаш напълно случайно, и е адски трудно да се reproduce-нат.

Stay Tuned!

(към част 1)

 Posted by at 8:54
Окт. 132009
 

Днес забелязах в сайта на Transaction Processing Performance Council (tpc) благата вест, публикувана тази нощ: Oracle си върна престижното първо място по tpc-c производителност.

Всъщност тази класация отдавна е само за престиж: мастодонтите, които заемат първите места са крайно непрактични и никой не би пуснал точно тази конфигурация. На мен лично, ми е по-интересна класацията за price/performance. Но пък да докажеш на света, че си изрод №1, си е тръпка… 🙂

На пръв прочит ми правят впечатление няколко неща. Първо, Oracle отново (6 години по-късно) постигат световен рекорд не с монолитна машина, а с клъстер, на който се търкаля Oracle RAC. По този начин те доказват, че саклируемостта на RAC не е (само) маркетингови приказки. В случая имаме 12-нодов клъстер. Освен това, факта, че много ядра на 1.6 GHz (UltraSPARC T2 Plus 48/384/3072 процесора/ядра/треда) могат да победят 6 пъти по-малко ядра на 5 GHz (IBM POWER6 32/64/128) говори за добрата скалируемост и в рамките на една единична машина.

Oracle удрят голямо рамо и на хардуера на SUN и на операционната им система (Solaris). Които, в скоро време, ще са собственост на Oracle :). Отдавна не е имало машина със елементи от SUN в top 10; в последните години железата са HP/IBM/FSC, а операционните системи са AIX/HP-UX/RHEL

За статистиката: резултата е 7 717 510.6 транзакции в минута (OLTP), като цената на системата (сървъри, сторидж, мрежова свързаност, лицензи, 3 години поддръжка) е $18 051 719 или 2.34 USD/tpmC. Сървърите са 12 със следните характеристики:
Sun SPARC Enterprise T5440
4 1.6GHz UltraSPARC T2 Plus
512GB Memory
2 300GB 10K rpm SAS disks
3 8Gbs FC dual port
2 4Gbs FC dual port
4RU High
Забелязвате ли – FC. Още не сме видели как ще се държи с infiniband 🙂

„Storage“ системата е многослойна, нещо като изродена Exadata2 на стероиди, ама на много. Състои се от:
4800 броя 24GB SSD Flash Modules
384 броя 300GB 15K rpm 2.5” SAS
24 броя 300GB 10K rpm 2.5” SAS (тия явно са в самите сървъри)
449 броя 1TB 7.2K rpm 3.5” SATA.
Тук също може да се отбележи интересен подход: всички други TPC-C рекорди са постигнати с огромно кличество от възможно най-малките като капацитет (разбирай – цена) 15К RPM дискове: 72 гигабайтови. Докато тук благодарение на 4800 flash cache адаптери са си позволили да използват „най-обикновени“ 1000 гигабайтови дискове – SATA!. За сравнение, вторият в класацията резултат има
8 броя 146.8GB 15K RPM SCSI в сървъра
10 992 броя 73.4GB 15K RPM 4Gb FC.

Тук можете да видите още много подробности за системата.

 Posted by at 13:51
Окт. 132009
 

А като си помисля, че се чудех дали да ходя – нали съм леко нестабилен здравословно, пък следобед ме заболя и гърло… Никога нямаше да разбера какво съм пропуснал.

Всичко по реда си. Доставих се пред залата към 19:40. Там се срещнах с Иван и двамата се вмъкнахме за няма и 10 минути. Направи ми впечатление, че почти всички седалки са за заети, а пред сцената, където е истинската веселба, имаше към 200 човека. Зачудих се да не съм попаднал на концерт на Веселин Маринов: бахти, да отидеш на метъл концерт и да седиш седнал… (всъщност и аз седнах, но си имах причини). Добре че до 9 часа постоянно прииждаха хора, та пространството се уплътни хубаво.

Вътре дънеха Furnaze (всъщност не познавам подгряващите банди, разчитам на снимките от сайта на SME). Не знам, може би остарявам, но това не беше моята музика. Много „хард“ ми дойде. За това с нетърпение очаквах да свършат. Всеки си има вкус…

След това дойде ред на Kings of Modest. Честно казано, очаквах поредната дрън-ня. Но момчетата ми допаднаха много. Свирят добър, мелодичен метъл. Вокала не се дере, а пее (т.е. и за него има мелодия). И явно бяха ужасно впечатлени от публиката, защото се счупиха да ни благодарят след абсолютно всяка песен. Ама и „подкрепата“ от залата беше силна. едва ли много от присъстващите са ги чували преди, камо ли да запеят някоя песен, но хубавата музика заслужава хубаво викане.

И така до 20:50, когато Kings of Modest се прибраха. Стана малко тъпо когато си тръгваха, публиката взе да скандира „Таря, Таря“… Един вид „Чухме ви, добри сте, ама освобождавайте по-бързо“. Но такава е съдбата на подгряващите групи…

Таря излезе около 21:20. И залата полудя.


(сн. Metal Katehezis)

А, вярвайте ми, залата беше пълна до край. В началото изгаснаха почти всички светлини и засвири музика (за да се настанят музикантите). В този момент от моят позиция (долу-горе на средата между сцената и края на залата) ми направиха впечатление светлинките от дисплеи на GSM-и и фотоапарати: май имаше около 2 апарата на квадратен метър. И аз съм я правил тая глупост – да се опитвам да запиша нещо от концерт. Но няма как да стане, защото хилавите камерки хич не се справят на тъмно. Пък и в напъна да снимаш пропускаш кефа…

За изпълненията на Таря не мога да говоря. Божествен глас, невероятно излъчване, динамика. Невъобразимо удоволствие, сякаш не е от този свят. Немислима комбинация от здрава жица и плътно, мелодично излъчване. Удоволствие в най-чист вид, цели 2 часа.

Няма да изрежда сет-листа. Не съм си играл да го помня. Само ще отбележа един интересен факт: за разлика от другите, утвърдени групи, на чиито концерти съм бил, Таря Турунен все още няма нейния световен хит. Да, всички, които бяхме там, познавахме добре песните и и я подкрепяхме много здраво (а си пролича, че и тя се радваше много на това). Но цялата публика припяваше масово само на песните на Nightwish и Alice Cooper.

След „бис“-а Таря направи нещо, което аз, лично, не съм виждал: слезе сред публиката, в центъра на тълпата, и изпълни няколко песни от там. Да, вярно, беше заобиколена от 2 реда горили, а и изпълняваше само най-спокойни песни, даже без жица, за да не подлудява тълпата. Но удоволствието от уважението, което показа пред нас, феновете, е невероятно. Представи си: снежната кралица (която до тогава беше сменила поне 2-3 тоалета и вече не беше с бяло), която кара няколкото хиляди хора да подскачат крещят от удоволствие, слиза сред нас и пее, сякаш сме на парти у дома. Незабравимо (особено за щастливците, които бяха около нея). Дори изкара една песен сама – „If you beleive“ или нещо такова, не я бях чувал – свири на клавишните, пее, а лицето и излъчва… добри неща.

п.с.Много добри снимки в Дневник

 Posted by at 8:50
Окт. 122009
 

Tarja Turunen

Два часа чисто удоволствие.

Подробностите – утре

 Posted by at 23:26

Jonathan Lewis в София

 Consultant, Общи  Коментарите са изключени за Jonathan Lewis в София
Окт. 122009
 

Dear Reader,
The first time I heard about Jonathan was in short email from Cary Millsap (after he left Oracle and formed Hotsos) with a pointer to Jonathan’s sexy and easy-to-remember web address http://www.jlcomp.daemon.co.uk/ and a short question: „Ever heard about this guy? Seems pretty smart.“

Pretty smart, indeed. I have called Jonathan „the future Dave Esnor“, but even that is not doing him full justice. He writes incredibly well. He even has the guts to tell an audience of more then 500 people that he considers his book the second-best on the market, with Tom Kyte’s first book being, well, the first. That might be so, but reading his book is still pure pleasure to me, and it would still be one of the three Oracle-related books I would bring to the famous desert island.

He forces the rest of us to ever higher standards when it comes to testing, testing, and testing (to destruction) before we write or claim anything. And he constantly reminds us that this of that experiment or observation is only true for this or that version of Oracle under this or that condition.

He shares any insights he gains with the World, and is in that and other respects the scientist we all want to become one day. He somehow finds time to answer more questions on comp.server.databases.oracle and the Oracle-L list than most. He teaches as he used to be a teacher (a teacher, that is, who cared about his job). Which he was, by the way. His presentations are always well prepared, well timed, and well worth your time.
. . .

С тези думи Mogens Nørgaard започва представянето на Jonathan Lewis, един от авторите на „Oracle Insights: Tales of the Oak Table„. Само това да беше, пак щях да хукна към двата семинара, който ще се проведе другата седмица. А съм чел и немалко неща, писани от него. Убеден съм, че който дойде, няма да съжалява.

 Posted by at 10:02

Shit mountain

 Junk, Общи  Коментарите са изключени за Shit mountain
Окт. 012009
 

Не знам нарочно ли са подбирали цветовете така:

Shit mountain

Това е гледката като в Oracle EM Grid Control. „Кафявата маса“ започва да се натрупва когато db_recovery_file_dest се напълни до указания размер и ARCH процеса не може да пише повече archivelogs. В този момент БД е почти неизползваема и картинката подсказва за проблема: сякаш се натрупва една планина от разноцветни л…а.

След увеличаване на db_recovery_file_dest_size, почти веднага се завръщат нормалните гледки: зелено като полянка, синьо като небето над нея… БД работи 🙂

 Posted by at 13:10