Да измерим service time

 Общи  Коментарите са изключени за Да измерим service time
Авг. 252014
 

Да ни е честита новата чудесна система. Дадохме за нея една торба пари, инсталираме я от маса време. Ама как да проверим дали се държи адекватно? Дали всички конфигурации са наред, дали не сме забравили нещо? Дали няма да се срине при go live? Дали работи поне толкова добре токова добре като настоящата…

Тези въпроси ме тормозят с внедряването на новата ни ексадата. Промяната не е малка – хардуер, ОС, че и RAC на всичкото отгоре.

За щастие си имаме QA, които могат да пуснат автоматизирани тестове и да следим как работи. Обаче отговора „така като гледам, изглежда добре“ не ме радва. Иска да знам точно как се държи системата.

Ако сте се интересували от теорията на опашките (примерно покрай моята лекция на БГПО), помните че

Response Time = Service Time + Waiti time

Servce time е точно това, което ми трябва – то е функция на системата и настройките. Дяволията е да се измери service time с достатъчна точност. За това си копирахме една production база на новото желязо, пуснахме си тестовете и започнахме да смятаме. Автоматизирания тест може да симулира текущия Peak production load с разни варианти – примерно 0.25х, 0.5х, 1х, 2х, 4х и т.н. Напомням, че за да се смята чист service time, ни трявба минимален (по възможност никакъв) wait time. Това се получава при нисък arrival rate. Сега, не че не пуснахме и 16х, щото ни сърбяха ръцете (между другото, издържахме го, но response time беше около 5х service time). Обаче за измерване на чистия service time пускахме 0.25х и 0.5х.

Ситуацията е следната: пускаме натоварването да върви известно време. Примерно правим някокло десетки хиляди плащания. Еталонно натоварване, повтаряемо. После замерваме DB time и делим времето на броя плащания. Така получаваме колко време се губи в БД за една бизнес транзакция, едно плащане. За удобство от време на време правим AWR snapshot. После ще ни трябва, за да установим натоварването.

Заявката се оказа по-корава, от колкото очаквах. Но в крайна сметка успях да установя средния db time per buiness transaction за всеки един AWR snapshot така:

select begin_interval_time, end_interval_time, trns, db_time_msec,
       decode(trns, 0, 0, db_time_msec / trns) msec_db_time_per_pay
  from (select m.snap_id, begin_interval_time, end_interval_time, m.dbid,
                (select count(1)
                    from -- your table with with business transactions goes here
                   where transaction_begin_time >= begin_interval_time -- get the number of transaction within the snapshot
                     and transaction_begin_time < end_interval_time) trns, 
								db_time_msec
           from dba_hist_snapshot s,
                (select snap_id, dbid, sum(db_time) / 1000 db_time_msec
                    from (select snap_id, dbid,
                                  value - lag(value, 1) over(partition by instance_number order by snap_id) db_time
                             from DBA_HIST_SYS_TIME_MODEL m
                            where stat_name = 'DB time')
                   group by snap_id, dbid) m
          where begin_interval_time > trunc(sysdate) -- take all snapshots for today
            and instance_number = 2 -- we want to take one row per snapshot, so we pick some instance. we aggregate the data from all instances later
            and m.snap_id = s.snap_id
            and m.dbid = s.dbid)
 order by 1

Така. Понеже знам, че на тази БД няма никакаво друго натоварване, си позволявам да взема целия DB time. Което не е много честно ако върви и нещо в паралел с нашия тест.

Това се забеляза болезнено когато решихме да замерим времето и на текущата production система. Понеже там освен нашия тест върви и реалния трафик, който е абсолютно разнороден (не само транзакции), се получават едни странни цифри. Така че за замерване на production направихме следното
– замерването го правим с 0.25x peak load
теста се пуска по време с ниско натоварване (при нас това е рано сутрин), за да няма много wait time
– направихме си един отделен service, на който да закачим тестовия application. Така можем да отделим натоварването от теста от всичките други неща които се случват в една production база
– разбира се, AWR репорти преди и след (и по време на) теста са задължителни

За измерване на db time вече не може да използваме DBA_HIST_SYS_TIME_MODEL. Но Oracle, в тяхната безкрайна мъдрост, са ни предоставили и DBA_HIST_SERVICE_STAT – същата статистика, разбита по service

select begin_interval_time, end_interval_time, trns, db_time_msec,
       decode(trns, 0, 0, db_time_msec / trns) msec_db_time_per_pay
  from (select m.snap_id, begin_interval_time, end_interval_time, m.dbid,
                (select count(1)
                    from -- your table with with business transactions goes here
                   where transaction_begin_time >= begin_interval_time -- get the number of transaction within the snapshot
                     and transaction_begin_time < end_interval_time
                     and ... -- make sure you take only the test transactions - you need some way to mark those in the application
										 ) trns, db_time_msec
           from dba_hist_snapshot s,
                (select snap_id, dbid, sum(db_time) / 1000 db_time_msec
                    from (select instance_number, sn.dbid, ss.snap_id, ss.value,
                                  ss.value - lag(ss.value, 1) over(partition by instance_number, sn.service_name order by snap_id) db_time
                             from DBA_HIST_SERVICE_NAME sn, DBA_HIST_SERVICE_STAT ss
                            where sn.dbid = ss.dbid
                              and sn.service_name_hash = ss.service_name_hash
                              and sn.service_name in (/*[your test service name goes here]*/)
                              and ss.stat_name = 'DB time')
                   group by snap_id, dbid) m
          where begin_interval_time > trunc(sysdate) -- take all snapshots for today
            and instance_number = 1 -- we want to take one row per snapshot, so we pick some instance. we aggregate the data from all instances later
            and m.snap_id = s.snap_id
            and m.dbid = s.dbid)
 order by 1
 Posted by at 16:36

„ORA-28000: the account is locked“ – понякога???

 Общи  Коментарите са изключени за „ORA-28000: the account is locked“ – понякога???
Авг. 082014
 

Това ме изненада, честно!

Един потребител ми се оплака, че си е объркал паролата няколко пъти и получава ORA-28000. Преди да го отключа, реших да проверя какво е станало – нали все пак потребителите са си потребители…

SQL> select account_status from dba_users where username = 'xxx';

ACCOUNT_STATUS
--------------------------------
OPEN

A! Шах с пешката. И започна един разговор…
– Ама сигурен ли си че е на тази база?
– Да!
(все пак проверих на всички бази, до които има достъп – навсякъде е OPEN)
– Ама сигурен ли си че използваш този потребител?
– Да!!
(все пак проверих всички потребители – ами има си някой заключени, но от месеци)
– Ама сигурен ли си че е точно тази грешка?
– Да!!! Веднъж минава, три-четири пъти ми дава тази грешка!
– WTF???
Това, че понякога минава ме втрещи още повече. Как, по дяволите, става това? Ако потребителя беше на по-малко то 1000 км, щях да поискам лично да дойде да ми покаже.
Но това нямаше да ми помогне…
Помолих потребителя да се закачи на Primary базата (вместо на Active DataGuard), за да мога да видя какво пише в DBA_AUDIT_SESSION. Никакъв проблем – всички логини бяха успешни.

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

ORA-28000 „the account is locked“ in the standby database, even after the account was unlocked in the primary. (Doc ID 1600401.1)

Applies to:
Oracle Database – Enterprise Edition – Version 11.1.0.6 to 11.2.0.4 [Release 11.1 to 11.2]
Information in this document applies to any platform.

Symptoms
A user’s account in an Active Dataguard standby database is locked, for example as a result of multiple logon attempts with a wrong password to that standby database. The user attempts to logon and gets an error ORA-28000 „the account is locked“. The database administrator unlock this user’s account in the primary database. Still, the user cannot connect to the standby, getting the same error ORA-28000.

Cause
A privileged user (a database administrator) must unlock account in the standby database. It is not enough to unlock the same account in the primary database. This is because the standby is open read-only and cannot update any tables. When a user’s account has to be locked on the standby database, it is locked only in memory there.

Solution
A privileged user (sysdba, the database administrator) must logon to the standby and unlock the account there. A message ORA-28015 „Account unlocked, but the database is open for read-only access“ confirms that the account is now unlocked in the standby database. From then on, the user can logon to the standby database without getting any error.

Това обясни не само защо в DBA_USERS всичко е наред, но и защо понякога успява
– първо, понеже базата е read-only, заключването не може да се отрази в DBA_USERS (демек USER$). За това като питам таблицата всичко е наред – там няма информация за заключването, тя се пази само в паметта на ADG instance. Което е някакъв странен компромис…
– понеже базата е RAC, а и очевидно това тайно местенце в паметта не е защитена от cache fusion, успеха в логването зависи от това на кой нод ще попаднеш. За това понякога става, а понякога – не.
– понеже на базата няма кой-знае-какъв load, успешно закачилите се сесии на потребителя на „не-заключения“ нод, колкото и мизерно натоварване да правят, са достатъчни, за да може server-side load-balancing да го хвърля по-често към „заключения“. Затова средно 1 от 4 логина минава.

Решението – пуснах и на двата нода на ADG:

SQL> alter user xxx account unlock;
alter user xxx account unlock
*
ERROR at line 1:
ORA-28015: Account unlocked, but the database is open for read-only access
 Posted by at 15:56