вторник, 22 сентября 2015 г.

Write parse failures to alert log file (ORA-10035)

Если нужно временно найти какой-то запрос который выбрасывает ошибку парсинга в приложении, можно воспользоваться следующим event'ом что бы увидеть текст:

oerr ora 10035
10035, 00000, "Write parse failures to alert log file"

Пробуем:

SQL> alter system set events '10035 trace name context forever, level 1';

System altered.

SQL> select 1 form dual;
select 1 form dual
              *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected

SQL> select owner,object_name,count(1) from dba_objects where owner='SYS' group by owner order by 3 desc;
select owner,object_name,count(1) from dba_objects where owner='SYS' group by owner order by 3 desc
             *
ERROR at line 1:
ORA-00979: not a GROUP BY expression

SQL>  alter system set events '10035 trace name context forever, off';

Проверяем наш alert.log:

OS Pid: 9040 executed alter system set events '10035 trace name context forever, level 1'
Tue Sep 22 19:57:01 2015
PARSE ERROR: ospid=9040, error=923 for statement:
Tue Sep 22 19:57:01 2015
select 1 form dual
Additional information: hd=0x150fc6bc8 phd=0x15227b9e0 flg=0x28 cisid=0 sid=0 ciuid=0 uid=0
PARSE ERROR: ospid=9040, error=979 for statement:
Tue Sep 22 19:57:05 2015
select owner,object_name,count(1) from dba_objects where owner='SYS' group by owner order by 3 desc
Additional information: hd=0x15083b580 phd=0x1508160f0 flg=0x20 cisid=0 sid=0 ciuid=0 uid=0
Tue Sep 22 19:58:37 2015
OS Pid: 9040 executed alter system set events '10035 trace name context forever, off'

понедельник, 7 сентября 2015 г.

ORA-01866: the datetime class is invalid

Небольшой пример того как можно получить ORA-01866 при вызове удаленного модуля через database link.
Все действия производим под пользователем test(create session,create database link,create procedure).
Создадим тестовую процедуру с выходным параметром:
SQL> create or replace procedure  test.testproc(vvv out timestamp)
  2  as
  3  begin
  4  null;
  5  return;
  6  end;
  7  /

Procedure created.

Далее создадим database link, для демонстрации, просто на самого себя:
SQL> create database link testlink using '(description=(address_list=(address=(protocol=tcp)(host=localhost)(port=1521)))(connect_data=(server=dedicated)(sid=orcl)))';

Database link created.

И выполним небольшой блок для того что бы получить ошибку:
SQL> declare
  2  myts timestamp;
  3  begin
  4  test.testproc@testlink(myts);
  5  end;
  6  /
declare
*
ERROR at line 1:
ORA-01866: the datetime class is invalid
ORA-06512: at line 4
Конечно, мы специально не присваивали переменной vvv в теле процедуры никаких значений, что и повлекло подобную ошибку при обращении через dblink.
При этом, без dblink'а все работает хорошо:
SQL> declare
  2  myts timestamp;
  3  begin
  4  test.testproc(myts);
  5  end;
  6  /

PL/SQL procedure successfully completed.
Поправим процедуру:
SQL> create or replace procedure  test.testproc(vvv out timestamp)
  2  as
  3  begin
  4  vvv:=null;
  5  return;
  6  end;
  7  /

Procedure created.
И повторим эксперимент:
SQL> declare
  2  myts timestamp;
  3  begin
  4  test.testproc@testlink(myts);
  5  end;
  6  /

PL/SQL procedure successfully completed.
Ошибка больше не возникает.

понедельник, 19 мая 2014 г.

Oracle database 12c security enhancements

Рассмотрим новые для 12c системные привелегии "inherit [any] privileges".

Для проверки нам понадобится небольшая заготовка:

create user test1 identified by test default tablespace users;
grant create session to test1;
grant create table to test1;
alter user test1 quota 100M on users;
create table test1.testtab(c0 number not null);
create user test2 identified by test default tablespace users;
grant create session to test2;
grant create procedure to test2;
grant create view to test2;



Так как по-умолчанию привилегия "inherit privileges" выдана PUBLIC'у, мы ее отберем:

revoke inherit privileges on user test1 from public;

Согласно документации, системная привелегия "inherit [any] privileges" контроллирует набор привелегий доступных процедурам/функциям
запускаемым с правами вызывающего пользователя(authid current_user).
Пользователь test2 в нашем случае, обладает более узким набором прав в бзе данных и он будет создавать у себя различные объекты,
предоставляя доступ к ним для пользователя test1.

create or replace procedure test2.testproc authid current_user as
begin
for i in 1..100 loop
execute immediate 'insert into test1.testtab(c0) values('||round(dbms_random.value(0,100))||')';
end loop;
commit;
end;
/
grant execute on test2.testproc to test1;

Итак, в процедуре мы пытаемся внести записи в таблицу пользователя test1, процедура объявлена как исполняющаяся с правами вызывающего пользователя,
inherit privileges для test1 мы отняли.
Теперь вызовем эту процедуру из-под пользователя test1:

SQL> exec test2.testproc;
BEGIN test2.testproc; END;

*
ERROR at line 1:
ORA-06598: insufficient INHERIT PRIVILEGES privilege
ORA-06512: at "TEST2.TESTPROC", line 1
ORA-06512: at line 1

Но если бы мы не отняли inherit privileges для test1 у PUBLIC'а или выдали бы inherit any privileges пользователю test2, то ошибки бы не было.
Дадим test2 привилегию наследовать права от test1:

SQL> grant inherit privileges on user test1 to test2;

Grant succeeded.

SQL> exec test2.testproc;

PL/SQL procedure successfully completed.

Эта привилегия также будет актуальна при создании представлений с использованием функций использующих права вызываемого пользователя:

create or replace function test2.testfunc return number authid current_user as
retval number;
begin
execute immediate 'select max(c0) from test1.testtab' into retval;
return retval;
exception when others then return null;
end;
/
create or replace view test2.testview1 bequeath definer as select testfunc() c0 from dual;
create or replace view test2.testview2 bequeath current_user as select testfunc() c0 from dual;
grant select on test2.testview1 to test1;
grant select on test2.testview2 to test1;

Представление test2.testview1 ожидаемо не будет работать, будучи объявленным как bequeath definer,
функция, вызываемая в приложении будет выдавать ошибку, т.к. прав на test1.testtab у пользователя test2 нет:

SQL> select * from test2.testview1;
select * from test2.testview1
       *
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "TEST2.TESTFUNC", line 4

Проверим как это работает под пользователем test1 для представления объявленного как bequeath current_user:

SQL> revoke inherit privileges on user test1 from test2;

Revoke succeeded.

SQL> select * from test2.testview2;
select * from test2.testview2
                    *
ERROR at line 1:
ORA-06598: insufficient INHERIT PRIVILEGES privilege

SQL> grant inherit privileges on user test1 to test2;

Grant succeeded.

SQL> select * from test2.testview2;

              C0
----------------
             100

вторник, 7 января 2014 г.

SQL Profile при часто выполняемых запросах

Небольшая иллюстрация того что если в вашей OLTP системе есть часто используемые запросы с привязанным sql profile'ом, то всегда нужно подумать прежде чем совершать различные, казалось бы, безобидные вещи, например, выдавать права на объекты.

Итак, наш запрос:
insert into test.t2 
(
select c0,b.c1,a.c2 
from test.t0 a
inner join test.t1 b using(c0)
where c0 between 500000 and 1000000
);

Посмотрим на его план:

SQL> @q
Connected.

Explained.

Plan hash value: 1792085932

---------------------------------------------------------------------------------
| Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |      | 47926 |  6692K|  1161   (1)| 12:31:13 |
|   1 |  LOAD TABLE CONVENTIONAL | T2   |       |       |            |          |
|*  2 |   HASH JOIN              |      | 47926 |  6692K|  1161   (1)| 12:31:13 |
|*  3 |    TABLE ACCESS FULL     | T0   | 47448 |   509K|   580   (0)| 06:15:27 |
|*  4 |    TABLE ACCESS FULL     | T1   | 50912 |  6562K|   580   (0)| 06:15:27 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("A"."C0"="B"."C0")
   3 - filter("A"."C0">=500000 AND "A"."C0"<=1000000)
   4 - filter("B"."C0">=500000 AND "B"."C0"<=1000000)

Note
-----
   - SQL profile "SYS_SQLPROF_01425ad4fde30000" used for this statement

22 rows selected.

У нас есть действующий профайл для запроса.
Предположим, нам потребовалось выдат права какому-то пользователю на таблички T0 или Т1.
Выдаем права и проверяем что происходит у нас с курсором:

SQL> select invalidations,executions,object_status,is_obsolete,sql_profile from v$sql where sql_id='abryha8r76gmp';

   INVALIDATIONS       EXECUTIONS OBJECT_STATUS     SQL_PROFILE
---------------- ---------------- ----------------  --------------------------------
               0                1 VALID             SYS_SQLPROF_01425ad4fde30000

SQL> grant select on t0 to test1;

Grant succeeded.

SQL> grant select on t1 to test1;

Grant succeeded.

SQL> select invalidations,executions,object_status,is_obsolete,sql_profile from v$sql where sql_id='abryha8r76gmp';

   INVALIDATIONS       EXECUTIONS OBJECT_STATUS     SQL_PROFILE
---------------- ---------------- ----------------  --------------------------------
               1                1 INVALID_UNAUTH    SYS_SQLPROF_01425ad4fde30000

Курсор инвалидировался из-за изменений прав доступа. Следующий запуск нашего запроса также форсирует проверку профайла, что может занять некоторое время, если запрос довольно сложный или объем данных внушителен.

SQL> alter session set events '10046 trace name context forever, level 12';

Session altered.

SQL> insert into test.t2
  2  (
  3  select c0,b.c1,a.c2
  4  from test.t0 a
  5  inner join test.t1 b using(c0)
  6  where c0 between 500000 and 1000000
  7  );

5035 rows created.

SQL> alter session set events '10046 trace name context off';

Session altered.

SQL> rollback;

Rollback complete.

SQL> select invalidations,executions,is_obsolete,object_status,sql_profile from v$sql where sql_id='abryha8r76gmp';

   INVALIDATIONS       EXECUTIONS  OBJECT_STATUS    SQL_PROFILE
---------------- ----------------  ---------------- --------------------------------
               1                1  VALID            SYS_SQLPROF_01425ad4fde30000

Заглянув в трейс файл, или, пробежавшись по нему tkprof'ом, можно увидеть следующее:

SQL ID: 5mzpa3fwjsm2c Plan Hash: 2594672137

SELECT /* DS_SVC */ /*+ cursor_sharing_exact dynamic_sampling(0) no_sql_tune
  no_monitoring optimizer_features_enable(default) */ SUM(C1)
FROM
 (SELECT /*+ qb_name("innerQuery") NO_INDEX_FFS( "B")  */ 1 AS C1 FROM
  "TEST"."T1" SAMPLE BLOCK(3.75287, 8) SEED(1)  "B") innerQuery


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.35       0.35          0       2230          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.35       0.35          0       2230          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 269     (recursive depth: 1)
********************************************************************************

SQL ID: 9m4013m0g9yzq Plan Hash: 1819681537

SELECT /* DS_SVC */ /*+ cursor_sharing_exact dynamic_sampling(0) no_sql_tune
  no_monitoring optimizer_features_enable(default) */ SUM(C1)
FROM
 (SELECT /*+ qb_name("innerQuery") NO_INDEX_FFS( "A")  */ 1 AS C1 FROM
  "TEST"."T0" SAMPLE BLOCK(3.75287, 8) SEED(1)  "A") innerQuery


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.36       0.36          0       2230          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.36       0.37          0       2230          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 269     (recursive depth: 1)

В данном случае проверка заняла незначительное время, но стоит помнить что курсор при этом держится в экслюзивном режиме, и все сессии пытающиеся выполнить наш запрос, повиснут на ожидании cursor: pin S wait on X.
В нагруженной системе при длительной проверке можно успеть собрать большую очередь ожидающих сессий.

понедельник, 5 августа 2013 г.

Oracle 12c new features: pga_aggregate_limit

В версии 12с появилась возможность задавать жесткое ограничение на размер PGA. 
Раньше такой возможности, порой, не хватало.
Отвечает за это параметр pga_aggregate_limit.
Стоит обратить внимание, что этот параметр не играет роли для пользователя SYS и для фоновых процессов.