EM Event: Critical:ORADB – Row(3): Supplied date is in the future

 Общи  Коментарите са изключени за EM Event: Critical:ORADB – Row(3): Supplied date is in the future
Окт. 282012
 

Да ни е честит на всички този гаден гнусен бъг. С преминаването към зимно часово време OEM 12c Cloud control започна да бълва стотици нотификации от рода на:

EM Event: Critical:ORADB – Row(3): Supplied date is in the future : now = Sun Oct 28 03:34:22 CET 2012 supplied value = Sun Oct 28 04:34:00 CET 2012

Или още по-гнусното

EM Event: Critical:ORADB – Row(1): Supplied date is in the future : now = Sun Oct 28 02:55:23 CEST 2012 supplied value = Sun Oct 28 02:55:20 CET 2012

Разбира се, в My Oracle Support не пише нищо по въпроса. Единственото подобно нещо е Bug 14258529, но той не е оправен.

За сега закърпих положението с рестарт на агентите. Изглежда, че се оправи – вече 15 минути няма такива нотификации. Ще ходя да си доспивам…

 Posted by at 2:53

Много бази – хилав сървър

 Общи  Коментарите са изключени за Много бази – хилав сървър
Окт. 142012
 

Добре, де. Сървъра не е хилав. Обаче не е и някакво чудо неземно. Все пак е Dev сървър, на него търкаляме Dev бази.

Проблемът е, че търкаляме 30 Dev бази на един сървър. Вярно, във всеки един момент активно работят само 5-6 от тях (или 1-2). Но не и като дойде време за събиране на статистики. Настъпи ли време за събиране на статистики… жална му майка на сървъра. Всичките 30 бази почват да въртят дисковете – въртят, сумтят… и дисковете клякат. ASM също кляка и понякога дори спира да respond-ва за няколко секунди. В екстремните случаи се случва няколко бази да загинат:

ORA-15064: communication failure with ASM instance
ORA-03113: end-of-file on communication channel
Process ID:
Session ID: 4 Serial number: 1
ASMB (ospid: 8290): terminating the instance due to error 15064

Тук е времето да уточня, че тези 30 бази се създават като копия на една „master“ база. Каквото има на нея – такова има на тях. Всеки developer или екип може да си пресъздаде базата като текущо копие на master базата, или, много по-рядко, като копие на базата на другарчето си. Така че ако на master базата пише статистиките да тръгнат в 22:00 часа, рано или късно всички други бази ще започнат да си събират статистики в 22:00. И това, всъщност, е най-най-тежкото нещо, което може да се случи на този сървър.

Ето и решението, което съчиних:

create or replace procedure p_scramble_stats_start as
  v_start_hour char(1);
  v_start_min char(2);
BEGIN
  -- disable
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."MONDAY_WINDOW"', force => TRUE);
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."TUESDAY_WINDOW"', force => TRUE);
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."WEDNESDAY_WINDOW"', force => TRUE);
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."THURSDAY_WINDOW"', force => TRUE);
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."FRIDAY_WINDOW"', force => TRUE);
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."SATURDAY_WINDOW"', force => TRUE);
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."SUNDAY_WINDOW"', force => TRUE);
  -- "choose" the time
  select to_char(ora_hash(instance_name, 6)), to_char(ora_hash(instance_name, 59))
    into v_start_hour, v_start_min
    from v$instance;
  -- set
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."MONDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=MON;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."TUESDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=TUE;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."WEDNESDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=WED;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."THURSDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=THU;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."FRIDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=FRI;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."SATURDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=SAT;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  DBMS_SCHEDULER.SET_ATTRIBUTE(name      => '"SYS"."SUNDAY_WINDOW"',
                               attribute => 'REPEAT_INTERVAL',
                               value     => 'freq=daily;byday=SUN;byhour='||v_start_hour||';byminute='||v_start_min||';bysecond=0');
  -- enable
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."MONDAY_WINDOW"');
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."TUESDAY_WINDOW"');
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."WEDNESDAY_WINDOW"');
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."THURSDAY_WINDOW"');
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."FRIDAY_WINDOW"');
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."SATURDAY_WINDOW"');
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."SUNDAY_WINDOW"');
END;

Тази процедура си избира произволен час и минута (от 00:00 до 6:59) на база името на инстанса. След това сетва всичките maintenance прозорци (в които се събират статистики) да се отварят в този час. В нашия случай събирането продължава от 5 до 15 минути на база, така че не е проблем.

Направих на всички бази един job, който всяка вечер в 22:00 да изпълнява тази процедура. Така който и да копира от master или от някой друг, ще бъде фикснат най-късно на следващата вечер.

И от тогава не сме имали такива проблеми.

 Posted by at 9:23

Manual SQL tunning task

 Общи  Коментарите са изключени за Manual SQL tunning task
Окт. 132012
 

Тествано на 11.2.0.2

SQL tunning advisor е страшна далавера. Е, изисква допълнителен лиценз за tunning pack, но върши работа, която за обикновен човек е практически невъзможна.

По-честият вариант е когато нещо се скапе в production и трябва спешно да се оправи. Ех, колко пъти ни е спасявал SQL tunning advisor в такива ситуации… Хем намира решение (без да ти се налага да разбираш какво, аджеба, прави тази заявка); хем прави профил – така не се налага промяна в кода на самото приложение. Аз лично не съм се и опитвал ръчно да правя профил, супер пипкава работа ми изглежда. Правил съм ръчно outline и това беше пипкаво.

Има, обаче, и един друг сценарий. Представете си един горд developer, който е сътворил заявка с 97 реда execution plan. И моли за съдействие при оптимизацията. Това нещо е извън възможностите за възприемане. А SQL tunning advisor минава за минути и в повечето случаи наистина дава добри идеи. Как да го пуснеш, обаче?

През Grid/Cloud control е лесно – цъкаш, цъкаш и става. Но какво парим, ако го няма Could control закачен към базата? Или ако просто искаме да видим някой съвет за едно query, което ни мъчи?

Всъщност става много лесно:

1. Създаване на таск:

DECLARE
  v_task VARCHAR2(30);
  v_sql  CLOB;
BEGIN
  v_sql     := 'SELECT ... FROM ... WHERE ...';
  v_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_text => v_sql, 
                                               user_name => 'HR', 
                                               scope => 'COMPREHENSIVE',
                                               time_limit => 3600, -- seconds
                                               task_name => 'tune_test2',
                                               description => 'Tune statement used for the new XYZ functionality.');
END;
/

2. Изпълнение. Това може да отнеме доста време, в зависимост от сложността на заявката и зададения лимит:

exec dbms_sqltune.execute_tuning_task(task_name => 'tune_test2');

3. Да видим резултата. Това е целта, всъщност

set long 90000 longchunksize 90000
set linesize 232 pagesize 9999
select dbms_sqltune.report_tuning_task('tune_test2') from dual;

DBMS_SQLTUNE.REPORT_TUNING_TASK('TUNE_TEST2')
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : tune_test2
Tuning Task Owner  : HR
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 3600
Completion Status  : COMPLETED
Started at         : 10/05/2012 12:07:10
Completed at       : 10/05/2012 12:12:13

-------------------------------------------------------------------------------
Schema Name: HR
SQL ID     : ba6g55fakh01v
SQL Text   : SELECT ...

-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------

1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  A potentially better execution plan was found for this statement.

  Recommendation (estimated benefit: 76.48%)
  ------------------------------------------
  - Consider accepting the recommended SQL profile.
    execute dbms_sqltune.accept_sql_profile(task_name => 'tune_test2',
            task_owner => 'HR', replace => TRUE);

-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------

1- Original With Adjusted Cost
------------------------------
Plan hash value: 2801951464

------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |                             |    21 |  1302 | 30711   (4)| 00:06:09 |
...
|  97 |    TABLE ACCESS FULL                     | MY_TAB                      |     2 |    10 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
...
  95 - access("E"."TEST_ID"="T"."TEST_ID")

2- Original With Adjusted Cost
------------------------------

-------------------------------------------------------------------------------
Error: cannot fetch explain plan for object: 1
-------------------------------------------------------------------------------

3- Using SQL Profile
--------------------
Plan hash value: 3439552619

------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |                             |    21 |  1302 |  7223   (2)| 00:01:27 |
....
|  97 |    TABLE ACCESS FULL                     | MY_TAB                      |     2 |    10 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
....
  95 - access("E"."TEST_ID"="T"."TEST_ID")

(Да, наистина го пусках това за заявка с 97 стъпки в плана и 95 филтъра. Естествено тук съм отрязал както заявката, така и плановете и предикатите )

4. Може и да приложим предложения план. Аз в случая исках само да видя съвета, но пък за да се измери реалната промяна, трябва да се тества наистина с пускане на заявката

execute dbms_sqltune.accept_sql_profile(task_name => 'tune_test2',  task_owner => 'HR', replace => TRUE);
 Posted by at 11:40