Да си мерим п******

 Без категория  5 Responses »
дек. 132010
 

Напоследък все по-вяло следя TPC-C рекордите. Както съм писал и преди, нещата там са твърде непрактични. Но все пак са интересни…

Преди 2 години (6 октомври 2008) IBM достигнаха резултат от 6,085,166 tpmC (OLTP транзакции в минута), което беше около 50% над най-доброто, постигано от Оracle по онова време. Тогава го отдадох това на бруталните POWER процесори, които са си IBM-ски. Истината е, че ако си хардуерен вендор, би могъл да слгобиш колкото си искаш скъпа конфигурация (говорим за милиони), да си направиш теста и после да я продадеш на части. По онова време Oracle не бяха хардуерен вендор и си правеха рекордите заедно с HP, което е по-трудно за организация.

Този рекорд на IBM оцеля повече от година, докато Oracle не си напазаруваха SUN. Тогава (3 ноември 2009) успяха да изкарат една напомпана версия на Oracle Database machine, нещо като exadata 2 конфигурация на стероиди, която докара 7,646,486 tpmC. Освен силата на SUN-ския хардуер, този резултат показа и скалируемостта на Oracle RAC.

Лятото на тази година (17 август 2010) IBM отвърнаха на удара с резултат от 10,366,254 tpmC. Това, че резултата е постигнат с DB2 върху AIX на POWER машини не е изненада. Интересното е, че вече IBM не могат да направят достатъчно голяма единична машина и за първи път показват клъстерен резултат (клъстер от 3 POWER 780 машини). Те нямат точно shared-everything клъстер, използвали са clustom application, но ще им повярваме. По-малката клюка е, че и при тях вече се появяват SSD модули – 224 х 177 GB.

Преди десетина дни Oracle успяха да разцепят мрака с бруталния резултат от 30,249,688 tpmC. Чудовищната кочина е направена от 27 Sun SPARC T3-4 сървъра, всеки от тях с 4 процесора с по 16 core-а на процесор и 8 thread-а на core – или общо 13824 thread-a. Е това ако не е доказателство за скалируем софтуер… Друг любопитен детайл е 11 040 SSD модула (всеки по 24 GB). Всичко е описано тук.

Това, че Oralce RAC е саклируем или факта, че Sun са набарали пулса на SSD технологията, е добре известно. По-важен е факта, че с този тест Oracle натъртват, че имат ясното намерение да извадят SPARC от калта и да го развиват като entrprise-клас платформа. Което е доста логично, всъщност. Itaium отадван не може да се мери с POWER, a x86 си е ширпотреба, колкото и да задобряват новите Xenon-и.

Друга интересна клюка е price/performace стойността, което са успяли да достигнат: 1.01 USD/tpmC, което е доста под резултата на IBM от 1.38 USD/tpmC. И двата резултата са постигнати с обещанието за космически отстъпки, но все пак са според правилата:

Prices used in TPC benchmarks reflect the actual prices a customer would pay for a one-time purchase of the stated components. Individually negotiated discounts are not permitted. Special prices based on assumptions about past or future purchases are not permitted. All discounts reflect standard pricing policies for the listed components.

И като стана дума за price/performace, това е другия фронт, на който Oracle радват фенското ми сърце. Там битката им е с Microsoft, които нямат шанс да се бият на Performace арената, но са агресивни в ценовата политика. Там е и много по-лесно да се правят тестове – едно е да затвориш $100К за теста, друго е $30М.

Текущия водач е 0.39 USD/tpmC, направен от Oracle Database 11g Release 2 Standard Ed One върху HP ProLiant ML350 G6 и много MSA-та. По повод на този резултат мога да злорадствам, че той е излязъл само две седмици преди цифрата 0.49 USD/tpmC (27 август), постигната от Microsoft SQL Server 2005. Имайки предвид, че такъв тест не се прави от днес за утре, сигурно е било много депресиращо за служителите от MS, подготвяли системата. Целта им е била чисто престижна – да подкопаят резултата от 0.50 USD/tpmC, постигнат миналата година от Oracle върху Windows.

 Posted by at 14:28

ORA-39165: Schema SYS was not found

 Без категория  Коментарите са изключени за ORA-39165: Schema SYS was not found
дек. 132010
 

Едно бързо напомняне – поради неизвестни причини, expdp 10.2 не работи върху таблици в схемите SYS, ORDSYS, EXFSYS, MDSYS, DMSYS, CTXSYS, ORDPLUGINS, LBACSYS, XDB, SI_INFORMTN_SCHEMA, DIP, DBSNMP и WMSYS. Тази мотика я настъпих при опит да си експортна sys.aud$, за да я закарам за анализ в друга база. Нъц – не може. Проблемът е описан в Metalink Note 553402.1, както и тук

Това е много тъжно. Една оправия е използването на добрите стари exp / imp. Които, обаче, са в пъти по-бавни на таблици с LOB колонки. Освен това нямат възможност да работят през db link, а реализацията на функционалност, аналогична на REMAP_TBLESPACE, е голямо приключение. Варианта за create table as select не е много готин, особено за големи обеми и натоварени бази. Мъка.

Още един интересен факт: по някаква причина expdp ми направи над 300 мегабайта physical reads преди да гръмне, че я нямало схемата SYS. Абе изобщо тоя ден ми беше черен.

 Posted by at 12:39
дек. 062010
 

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

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

Уважаеми [NAME],

Вие, получава 5% процента отстъпка от …. под форматан купон (номер на купона 2010) при всяка една покупка до края на 2010 година по случай новогодишните празници. Зарадвайте …. за новогидшните празници

Номере на купона 2010

Посетете сайта: …..

С уважение, екип на ….
телефон: ….
сайт: ….

Съгласно ЗЕТ ви информираме, че това може да е непоискано търговско съобщение* и съдържа информация за рекламните услуги предлагани от нас.

(многоточията са от мен, нямам намерение да им правя реклама, bold-а – също)
Така. Първо, не се казвам [NAME], това е ясно. Да кажем, че това е някаква техническа грешка – гадно е, но се случва.

Обаче освен този технически дефект, почти всичко е супер некадърно написано. Е добре, как сега да си купя нещо от тях? Дори да забравим, че са спамери (което веднага ме отблъсква, но те не го осъзнават), недоклатеното им писмо не вдъхва професионализъм. Ама никак.

 Posted by at 11:57
ное. 222010
 

Презентацията от моята сесия на сбирката на БГПО в Правец може да изтеглите от тук: цък

Искам да изкажа моите огромни благодарности за Милена и другите организатори, които отново надминаха себе си и направиха невероятен семинар. Презентациите на Дан Морган печелят личната ми класация за „best of bgoug nov’10“. Юлиян за пореден път печели приза ми за общуване с публиката.

За мен кулминацията беше личната ми AskTom сесия в събота вечерта, когато на водка (за мен) и шуменско (за Том) си говорихме за живота, индексите и всичко останало.

Цялата сбирка си беше истински пир за Oracle-ската ми душа 🙂

 Posted by at 12:35

Въпрос на статистика, част 3

 Общи  Коментарите са изключени за Въпрос на статистика, част 3
ное. 012010
 

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

Та въпроса е: трябва да се намери стойността на дадена системна статистика от AWR репортите (примерно използваното PGA). Да, ама не може да сравнявам стойността в 3 следобед с тази в 3 през нощта. За това искам да гледам само репорти, които са +/- 2.1 часа от сегашния момент. Т.е. в 3 през нощта ще гледам от 1 до 5 през нощта.

И ето я великата заявка:

select p.value
  from dba_hist_pgastat p, dba_hist_snapshot s
 where s.snap_id = p.snap_id
   and p.name = 'total PGA allocated'
   and s.end_interval_time > sysdate - 60
   and abs(remainder(cast(s.end_interval_time as date)-sysdate, 1)) < 2.1/24;

Грубо казано действа така
- взема разликата между sysdate и датата на awr snapshot-а. Разликата е в дни. Действа за сравнение на всякакви дати, т.е. няма значение коя е по-нова
- отрязва само часовете (т.е. премахва цялата част - дните) с помощта на remainder. Красивото тук е, че действа и в "гранични" стойности, примерно в 1 през нощта ще вземе и 23 от предния ден (и обратно). Направо не вярвах, че ще се получи толкова елегантно! 🙂
- сравнява със зададения лимит, в случая 2.1 часа (2.1/24)

После този резултат може да се прекара през заявката, която далновидно си записах миналата година, за да се вадят изводи дали, аджеба, сме на "нормално" ниво или нещо не е наред.

Важно за успеха тук е да си пазим достатъчно стари awr репорти. Статистическия апарат, който ми подсказахте миналата година, работи добре при над 30 наблюдения.

 Posted by at 12:47
окт. 202010
 

Днес се сблъсках с този проблем и искам да споделя решението, което открих в блога на Харалд.

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

Очевидното в плана беше, че се прави FTS (Full Table Scan, да не се бърка с Formula Telecom Solutins 😉 ) на една от най-тлъстите ни таблици. И това се виждаше само в v$sql_plan – ако дам explain plan обещава, да мине през индекс.

Използвах SELECT * FROM TABLE(dbms_xplan.display_awr(‘&sql_id’)); и видях, че плана е сгъбен от днес. Старите планове си минаваха през индекс. Защо се е променил (и то към лошо) – така и не се разбра. Не задълбах много в тази насока. Въпроса беше как мога да я изгоня от library cache, за да се генерира нов план.

Най-драстичното решение е alter system flush shared_pool. Но това е като да си запалиш къщата, за да изгониш една мишка от нея. Да, този план вероятно ще се оправи, друг може пък да се счупи, а това ще е придружено от маса CPU докато се напарснат всички заявки. Не, благодаря.

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

Решението, което предлага Харалд, е много елегантно. Пакета dbms_shared_pool има процедура purge, която прави точно това – изритва нещо (било то курсор, пакет, или друго) от library cache. По принцип тя е нова в 11.1, но е толкова ценна, че са я добавили в 10.2.0.4. Има, обаче, две подробности.

Първо, в нашата версия на dbms_shared_pool нямаше тази процедура. Това се оправя лесно:
@?/rdbms/admin/dbmspool

След това тествах, тествах – то не бачка. Процедурата си минава, но не прави нищо полезно. Тогава се зачетох из коментарите на блога на Харалд и намерих това:
alter session set events '5614566 trace name context forever';

След това нещата потръгнаха:
select address, hash_value from v$sqlarea where sql_id = '1mqxxf66dtgdp';
exec sys.dbms_shared_pool.PURGE('0000000A5C166350, 2363276725', 'C');

Тук параметъра C идва да покаже, че гоним курсор. По същия начин може да се изритат и други неща:
– Value Kind of Object to keep
– –– –––––––-
– P package/procedure/function
– Q sequence
– R trigger
– T type
– JS java source
– JC java class
– JR java resource
– JD java shared data
– C cursor

Ta… това е. Мисля, че е полезно. И работи, тествано е.

 Posted by at 17:56

ASM 11.2 error ORA-15038

 Без категория  Коментарите са изключени за ASM 11.2 error ORA-15038
окт. 152010
 

Грешката идва при стартиране на ASM instance или при ръчно монтиране на група.

ORA-15032: not all alterations performed
ORA-15040: diskgroup is incomplete
. . .
ORA-15038: disk **** mismatch on 'Time Stamp' with target disk group [1752361090] [1751191692]

На нас ни се случи точно след Upgrade на ASM и за момент настана спек (и спар). Лично на мен първата ми мисъл беше, че при ъпгрейда се е омазал хедъра на някой от дисковете.

Но се оказа, че дявола не е толкова черен. Проблема е в параметъра asm_diskstring. След като сложихме правилния стринг всичко заспа.

11.1 даваше по-мили грешки…

 Posted by at 11:52

Цитат на деня

 Без категория  Коментарите са изключени за Цитат на деня
окт. 112010
 

Complexity is the IT equivalent of communist bureaucracy – it isn’t remotely interesting, it wastes colossal amounts of time, and it ultimately causes the system to go down.

Аз бих го свързал с всяка тежка бюрокрация – била тя комунистическа, брюкселска или вашнгтонска…

Credits: James Morale’s blog – Sane SAN 2010: Fibre Channel – Ready, Aim, Fire

 Posted by at 16:56

Ако не е едно, ще е друго…

 Без категория  Коментарите са изключени за Ако не е едно, ще е друго…
окт. 082010
 

Това е част от Upgrade скрипта на 11.2.0.2:

#######################################################################
#######################################################################
## The following statement may cause an
## ORA-29554: unhandled Java out of memory condition
## error.
## If so, this is because there is insufficient system tablespace,
## shared or java pool size, or some other resource value is too small.
## An additional message describing the problem will be output by
## the statement.
#######################################################################
#######################################################################

Демек, „ако това гръмне, значи нещо не стига, оправи го“ 🙂

Между другото, евалата на тоя скрипт, до сега съм пуснал бая ъпгрейди към 11.2 и всичките минават безгрижно. Трябва само да се изпълнят препоръките от utlu112i.

(не съм пробвал през DBUA, но вероятно и той работи)

 Posted by at 15:30

UPDATE GLOBAL INDEXES – testing suite

 Общи  Коментарите са изключени за UPDATE GLOBAL INDEXES – testing suite
авг. 302010
 

За да възпроизведа проблемите, описани в статията; както и за да тествам евентуалните решения, драснах набързо един тестова пакет. Има си кусури – примерно не се държи правилно ако config таблицата е празна – но за решение „набързо“ се получи добре. Всъщност толкова добре, че реших да го сложа тук, да не го загубя 🙂

Идеята е следната: с едно елементарно скриптче се пускат произволен брой sql*plus сесии (аз пробвах с 20 и 40).

for i in `seq 1 20`;
do
  sqlplus /nolog @loader.sql &
done;

Всяка от тях извиква процедурата start_single_process и толкова.

Зареждането започва с извикване (от друга – контролна – сесия) на start_load. Добре е да се зададе някакъв wait, пък бил той и 0.01 сек. Иначе става тегаво.

По всяко време зареждането може да бъде прекъснато с pause_load. Извикването на stop_load кара sql*plus сесиите да приключат.

create or replace package multi_ses_load is

  c_status_start constant number := 1; -- the LOADER sessions should run
  c_status_pause constant number := 0; -- the LOADER sessions should stop
  c_status_exit  constant number := 2; -- the LOADER sessions should exit
  -- every LOADER process should call this procedure. The procedure will wait for the START signal
  procedure start_single_process;

  -- issies the START signal. Parameters:
  --    part_no: in which partition should we load data
  --    wait: how many seconds to wait between 2 inserts
  --    refresh_iterations: how often to refresh the data from the config table
  procedure start_load(in_part_no            in number,
                       in_wait_sec           in number default 0,
                       in_refresh_iterations in number default 10);

  -- changes in which partition should we load data
  procedure change_part(in_part_no in number);

  -- changes how many seconds to wait between 2 inserts
  procedure change_wait(in_wait_sec in number);

  -- changes how often to refresh the data flrom the config table
  procedure change_refresh(in_refresh_iterations in number);

  -- stops the load process until another START signal
  procedure pause_load;

  -- restarts the load without changing any parameters
  procedure restart_load;

  -- makes the loading processes to exit
  procedure stop_load;

end multi_ses_load;

create or replace package body multi_ses_load is

  c_alert_name constant varchar2(20) := 'SESS_ALERT';

  -- every LOADER process should call this procedure. The procedure will wait for the START signal
  procedure start_single_process is
    v_alert_msg          VARCHAR2(1800);
    v_alert_status       PLS_INTEGER;
    v_part_no            number;
    v_wait_sec           number;
    v_refresh_iterations number;
    v_curr_stat          number;
    v_ses_clob           clob;
    v_my_sid             number;
    v_seed               number;
    procedure read_config_vars is
    begin
      -- reed the config variables form teh config table
      select curr_stat, part_no, wait_sec, refresh_iterations
        into v_curr_stat, v_part_no, v_wait_sec, v_refresh_iterations
        from ses_load_parames;
    end;
  
  begin
    -- init the random generator. we will use the current SID and number of seconds since mignight for seed
    Select Sid
      into v_my_sid
      from v$mystat
     where rownum = 1;
    v_seed := (sysdate - trunc(sysdate)) * 1000 * (24 * 60 * 60) + v_my_sid;
    dbms_random.initialize(v_seed);
    -- read the config vars
    read_config_vars;
    while v_curr_stat in (c_status_start, c_status_pause) -- if the current status is START or PAUSE, we proceed; 
     loop
      if v_curr_stat = c_status_pause then
        -- if the status us PAUSE, wait for the signal
        -- we should register the current session as a consumer for the alert
        dbms_alert.register(c_alert_name);
        -- now we can wait for the alert
        dbms_alert.waitone(c_alert_name, v_alert_msg, v_alert_status);
        -- refresh the config vars - they may be changed
        read_config_vars;
        if v_curr_stat = c_status_exit then
          exit;
        end if;
      end if;
      -- do 'v_refresh_iterations' inserts
      for i in 1 .. v_refresh_iterations loop
        -- insert a row into 'v_part_no' partition
        insert into ...
        values (dbms_random.string('P', 32), ...); -- here we should take care of the partition placement
        commit;
        dbms_lock.sleep(v_wait_sec); -- wiat for 'v_wait_sec' seconds
      end loop;
      -- refresh the config vars after whe have done enough iterations 
      read_config_vars;
    end loop;
  end;

  -- issues the START signal. Parameters:
  --    part_no: in which partition should we load data
  --    wait: how many seconds to wait between 2 inserts
  --    refresh_iterations: how often to refresh the data flrom the config table
  procedure start_load(in_part_no            in number,
                       in_wait_sec           in number default 0,
                       in_refresh_iterations in number default 10) is
  begin
    -- we set the parameters in the config table
    update ses_load_parames
       set curr_stat = c_status_start, part_no = in_part_no, wait_sec = in_wait_sec,
           refresh_iterations = in_refresh_iterations;
    commit;
    -- set teh LOADER processes free :)
    dbms_alert.signal(c_alert_name, 'Газ!');
    commit;
  end;

  -- changes in which partition should we load data
  procedure change_part(in_part_no in number) is
  begin
    update ses_load_parames
       set part_no = in_part_no;
    commit;
  end;

  -- changes how many seconds to wait between 2 inserts
  procedure change_wait(in_wait_sec in number) is
  begin
    update ses_load_parames
       set wait_sec = in_wait_sec;
    commit;
  end;

  -- changes how often to refresh the data flrom the config table
  procedure change_refresh(in_refresh_iterations in number) is
  begin
    update ses_load_parames
       set refresh_iterations = in_refresh_iterations;
    commit;
  end;

  -- stops the load process until another START signal
  procedure pause_load is
  begin
    update ses_load_parames
       set curr_stat = c_status_pause;
    commit;
  end;

  -- restarts the load without changing any parameters
  procedure restart_load is
  begin
    -- we set the parameters in the config table
    update ses_load_parames
       set curr_stat = c_status_start;
    commit;
    -- set the LOADER processes free :)
    dbms_alert.signal(c_alert_name, 'Аре пак на пангара!');
    commit;
  end;

  -- makes the loading processes to exit
  procedure stop_load is
  begin
    -- put the exit flag in teh table
    update ses_load_parames
       set curr_stat = c_status_exit;
    commit;
    -- is some process is in PAUSE, we should alert him to reread the config vars
    dbms_alert.signal(c_alert_name, 'Аре да си одиме, момчета!');
    commit;
  end;

end multi_ses_load;
 Posted by at 16:21