вторник, 23 октября 2012 г.

Capture any failed SQL queries using database trigger in Oracle

Создаем таблицу куда будем записывать запросы с ошибками:
  1. CONNECT SYSTEM;
  2.  
  3. DROP TABLE servererror_log;
  4.  
  5. CREATE TABLE servererror_log (
  6. error_datetime TIMESTAMP,
  7. error_user VARCHAR2(30),
  8. db_name VARCHAR2(30),
  9. error_stack VARCHAR2(2000),
  10. call_stack VARCHAR2(2000),
  11. SID NUMBER,
  12. SQL_ID VARCHAR2 (13),
  13. sql_statement VARCHAR2(2000),
  14. sql_statement_all CLOB,
  15. CLIENT_INFO VARCHAR2(256 BYTE),
  16. CURR_SCHEMA VARCHAR2(256 BYTE),
  17. CURR_USER VARCHAR2(256 BYTE),
  18. CURR_DB_NAME VARCHAR2(256 BYTE),
  19. HOST VARCHAR2(256 BYTE),
  20. IP VARCHAR2(256 BYTE),
  21. OSUSER VARCHAR2(256 BYTE),
  22. SESSID VARCHAR2(256 BYTE),
  23. SESS_USER VARCHAR2(256 BYTE),
  24. TERMINAL VARCHAR2(256 BYTE)
  25. );
  26.  
  27. GRANT SELECT, INSERT, UPDATE, DELETE ON SYSTEM.SERVERERROR_LOG TO SCOTT;
Выдаем явный грант на V_$SESSION пользователю SYSTEM для того чтобы триггер log_server_errors указанный ниже скомпилировался.
  1. CONNECT SYS AS SYSDBA;
  2. GRANT SELECT ON V_$SESSION TO SYSTEM;
Триггер базы данных на SERVERERROR(в условии WHEN можем исключить ошибки которые не нужно логгировать, в данном примере - это ORA-25254):
  1. CONNECT SYSTEM;
  2.  
  3. DROP TRIGGER log_server_errors;
  4.  
  5. CREATE OR REPLACE TRIGGER log_server_errors
  6. AFTER SERVERERROR
  7. ON DATABASE WHEN (
  8. ORA_SERVER_ERROR(1)<>25254 /*ORA-25254: time-out in LISTEN while waiting for a message*/
  9. )
  10. DECLARE
  11. v_sql_statement VARCHAR2(32767);
  12. sql_text ora_name_list_t;
  13. n pls_integer;
  14. cursor c_user is
  15. select vs.sid sid,
  16. vs.sql_id sql_id,
  17. sys_context('USERENV','CLIENT_INFO') client_info,
  18. sys_context('USERENV','CURRENT_SCHEMA') curr_schema,
  19. sys_context('USERENV','CURRENT_USER') curr_user,
  20. sys_context('USERENV','DB_NAME') db_name,
  21. sys_context('USERENV','HOST') host,
  22. sys_context('USERENV','IP_ADDRESS') ip,
  23. sys_context('USERENV','OS_USER') osuser,
  24. sys_context('USERENV','SESSIONID') sessid,
  25. sys_context('USERENV','SESSION_USER') sess_user,
  26. sys_context('USERENV','TERMINAL') terminal
  27. from dual
  28. cross join v$session vs
  29. where 1 = 1
  30. and sys_context('USERENV','SESSIONID') = audsid
  31. ;
  32. user_rec c_user%rowtype;
  33. BEGIN
  34. open c_user;
  35. fetch c_user into user_rec;
  36. close c_user;
  37.  
  38. n := ora_sql_txt(sql_text);
  39. FOR i IN 1..n LOOP
  40. v_sql_statement := v_sql_statement || sql_text(i);
  41. END LOOP;
  42. INSERT INTO servererror_log(
  43. error_datetime, error_user, db_name,
  44. error_stack, call_stack,
  45. SID, SQL_ID,
  46. sql_statement, sql_statement_all,
  47. CLIENT_INFO, CURR_SCHEMA, CURR_USER, CURR_DB_NAME,
  48. HOST, IP, OSUSER, SESSID,
  49. SESS_USER, TERMINAL
  50. ) VALUES(
  51. systimestamp, sys.login_user, sys.database_name,
  52. ora_server_error_msg(1)/*dbms_utility.format_error_stack*/,
  53. dbms_utility.format_call_stack,
  54. user_rec.sid, user_rec.sql_id,
  55. substrb(v_sql_statement, 1, 2000),
  56. v_sql_statement,
  57. user_rec.client_info, user_rec.curr_schema, user_rec.curr_user,
  58. user_rec.db_name, user_rec.host, user_rec.ip,
  59. user_rec.osuser, user_rec.sessid, user_rec.sess_user,
  60. user_rec.terminal
  61. );
  62. --commit;
  63. END;
  64. /
Выбираем запросы с ошибками(см. поля SID, SQL_STATEMENT, SQL_STATEMENT_ALL):
  1. CONNECT SCOTT;
  2.  
  3. select * from system.servererror_log
  4. --where ERROR_USER = 'SCOTT'
  5. order by error_datetime desc
  6. ;
Дополнительные команды которые возможно пригодятся для трассировки сессии:
  1. CONNECT SYSTEM;
  2.  
  3. ALTER SYSTEM SET sql_trace = true SCOPE=MEMORY;
  4. ...
  5. select * from system.servererror_log;
  6. ...
  7.  
  8. ALTER SYSTEM SET sql_trace = false SCOPE=MEMORY;
  9.  
  10. --After Logon Trigger for Tracing on Schema:
  11. CONNECT SCOTT;
  12.  
  13. CREATE OR REPLACE TRIGGER SCOTT_AFTER_LOGON_TRG_00
  14. AFTER LOGON ON SCOTT.SCHEMA
  15. DECLARE
  16. sqlstr VARCHAR2(200) := 'ALTER SESSION SET EVENTS ''10046 TRACE NAME CONTEXT FOREVER, LEVEL 4''';
  17. BEGIN
  18. IF (USER = 'SCOTT') THEN
  19. execute immediate sqlstr;
  20. END IF;
  21. END;
  22. /

среда, 19 сентября 2012 г.

How to viewing Oracle bind variable values?

  View V$SQL_BIND_CAPTURE has been introduced to report information on bind variables used by SQL cursors.

  Following query uses the sql_id address that should be specified for each unique SQL statement:

set linesize 256
set pagesize 54
set scan on
set heading on termout on verify off echo off

col KILL_SERIAL_SID format a52
col sql_text format a50 wrap
col name format a15 wrap
col datatype_string format a30
col value_string format a30 wrap

SELECT
   ss.serial#,
   ss.sid,
   --ALTER SYSTEM KILL SESSION '573,31517' IMMEDIATE
   'ALTER SYSTEM KILL SESSION ''' || ss.sid || ',' || ss.serial# || ''' IMMEDIATE;' kill_serial_sid,   
   b.name,
   b.position,
   b.datatype_string,
   b.value_string,
   a.sql_text
FROM
  v$sql_bind_capture b,
  v$sqlarea          a,
  v$sql s,
  v$session ss
WHERE 1 = 1
AND s.sql_id = a.sql_id   
AND b.sql_id = a.sql_id
-- Join v$session to v$sqlarea 
--AND ss.sql_address = a.address 
--AND ss.sql_hash_value = a.hash_value
--
-- Join v$session to v$sql 
--AND ss.SQL_ADDRESS = s.ADDRESS
-- joining on SQL_ID is much more efficient
AND ss.sql_id = s.sql_id
-- To capture only active session with specified SQL_ID
--AND ss.STATUS = 'ACTIVE'
AND b.sql_id = '&sql_id' --'4453zzgmqssxr'
;

You can get the SQL ID from the v$sql view:

set linesize 256
set pagesize 54
set scan on
set heading on termout on verify off echo off

col sql_text format a130 wrap
col bind_name format a35 wrap
col bind_string format a50 wrap

select
  sql_id,
  t.sql_text SQL_TEXT,
  b.name BIND_NAME,
  b.value_string BIND_STRING
from
  v$sql t
  join v$sql_bind_capture b
  using (sql_id)
where
  b.value_string is not null
  and sql_id='&sql_id' --'f8pavn1bvsj7t'
;

How to viewing in SQL Monitor of Enterprise Manager 11g
   Offline Analysis of Long Running SQL using SQL Monitoring Active Reports

Using 10046 trace for tracing bind variable values
  You can run a 10046 level 4 trace to debug code with bind variables and see the bind variable values as it steps through the code:

EXECUTE sys.dbms_system.set_ev ('||SID||','||SERIAL#||',10046,4,'''')

Bind Capture History

set linesize 256
set pagesize 54
set scan on
set heading on termout on verify off echo off

col name format a50 wrap
col value_string format a50 wrap

VARIABLE sql_id VARCHAR2(50)
EXEC :sql_id := '4453zzgmqssxr'

select snap_id, name, position, value_string, last_captured
  from dba_hist_sqlbind
 where sql_id = :sql_id
 order by snap_id desc;

среда, 11 апреля 2012 г.

Reading alert log via SQL in Oracle 11g

X$DBGALERTEXT показывает последний log.xml

X$DIAG_ALERT_EXT показывает объединенное содержимое для файлов log_XX.xml, включая log.xml.

  1. connect sys as sysdba
  2.  
  3. select * from X$DBGALERTEXT where rownum <= 20;
  4.  
  5.  
  6. set linesize 254
  7. col ORIGINATING_TIMESTAMP format a50
  8. col MESSAGE_TEXT format a170
  9.  
  10. SELECT ORIGINATING_TIMESTAMP, message_text FROM X$DIAG_ALERT_EXT
  11. where 1 = 1
  12. and originating_timestamp >= sysdate - 30
  13. and message_text like 'ALTER SYSTEM%'
  14. and message_text not like 'ALTER SYSTEM ARCHIVE LOG%'
  15. ;

Select ORA-XXXXX and TNS-XXXXX errors last 10 minutes:
  1. set linesize 254
  2. col ORIGINATING_TIMESTAMP format a50
  3. col MESSAGE_TEXT format a170
  4.  
  5. SELECT inst_id, originating_timestamp, MESSAGE_TEXT
  6. FROM TABLE (
  7. gv$ (
  8. CURSOR (
  9. SELECT inst_id, originating_timestamp, MESSAGE_TEXT
  10. FROM v$diag_alert_ext
  11. WHERE originating_timestamp > (SYSDATE - 10/1440)
  12. AND (MESSAGE_TEXT LIKE '%ORA-%' or MESSAGE_TEXT LIKE '%TNS-%')
  13. AND MESSAGE_TEXT NOT LIKE '%TNS-12502%'
  14. )
  15. )
  16. )
  17. ORDER BY inst_id, originating_timestamp;

пятница, 9 марта 2012 г.

Shrinking temporary tablespace in Oracle 10g and 11g

Useful links

Shrinking temporary tablespace in Oracle 10g

  1. CREATE TEMPORARY TABLESPACE TEMP02 TEMPFILE
  2. '/oracle/oradata/db/TEMP_02.dbf' SIZE 50M AUTOEXTEND ON;
  3.  
  4. ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP02;
Switch all existing users from old TEMP to new TEMP02 tablespace:
  1. set serveroutput on
  2. -- Switch all existing users to new temp tablespace.
  3. BEGIN
  4. FOR cur_user IN (SELECT username FROM dba_users WHERE temporary_tablespace = 'TEMP') LOOP
  5. dbms_output.put_line('ALTER USER ' || cur_user.username || ' TEMPORARY TABLESPACE TEMP02');
  6. EXECUTE IMMEDIATE 'ALTER USER ' || cur_user.username || ' TEMPORARY TABLESPACE TEMP02';
  7. END LOOP;
  8. END;
  9. /

Waiting for release old TEMP tablespace usage by applications/sessions:

  1. lsof | grep temp01.dbf | wc -l
  2. 124
  1. select count(*) from V$TEMPSEG_USAGE
  2. where tablespace = 'TEMP';
  3.  
  4. COUNT(*)
  5. ----------
  6. 91
  1. select tablespace, username, count(*)
  2. from V$TEMPSEG_USAGE
  3. where 1 = 1
  4. --and tablespace in ('TEMP', 'TEMP02')
  5. and tablespace = 'TEMP'
  6. group by tablespace, username;
when count become zero then drop unused old TEMP tablespace and files:
  1. DROP TABLESPACE TEMP INCLUDING CONTENTS AND DATAFILES;

Recreate old TEMP tablespace and if you want switch back from TEMP02

  1. CREATE TEMPORARY TABLESPACE TEMP TEMPFILE
  2. '/oracle/oradata/db/TEMP_01.dbf' SIZE 50M AUTOEXTEND ON;
  3.  
  4. ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP;
Switch all existing users back to TEMP tablespace:
  1. set serveroutput on
  2. -- Switch all existing users to new temp tablespace.
  3. BEGIN
  4. FOR cur_user IN (SELECT username FROM dba_users WHERE temporary_tablespace = 'TEMP02') LOOP
  5. dbms_output.put_line('ALTER USER ' || cur_user.username || ' TEMPORARY TABLESPACE TEMP');
  6. EXECUTE IMMEDIATE 'ALTER USER ' || cur_user.username || ' TEMPORARY TABLESPACE TEMP';
  7. END LOOP;
  8. END;
  9. /

Waiting for release TEMP02 tablespace usage by applications/sessions:

  1. lsof | grep temp02.dbf | wc -l
  2. 124
  1. select count(*) from V$TEMPSEG_USAGE
  2. where tablespace = 'TEMP02';
  3.  
  4. COUNT(*)
  5. ----------
  6. 91
  1. select tablespace, username, count(*)
  2. from V$TEMPSEG_USAGE
  3. where 1 = 1
  4. --and tablespace in ('TEMP', 'TEMP02')
  5. and tablespace = 'TEMP02'
  6. group by tablespace, username;
when count become zero then drop unused TEMP02 tablespace and files:
  1. DROP TABLESPACE TEMP02 INCLUDING CONTENTS AND DATAFILES;

Temporary Tablespace Enhancements in Oracle Database 11g

  1. alter tablespace temp shrink space [keep 100m];

The shrink can also be directed to a specific tempfile using the TEMPFILE clause.
  1. ALTER TABLESPACE temp SHRINK TEMPFILE '/oracle/oradata/db/temp01.dbf' KEEP 30M;

View V$TEMPSEG_USAGE

  1. lsof | grep temp01.dbf | wc -l
  2. 124
  1. select * from V$TEMPSEG_USAGE
  1. select count(*)
  2. from V$TEMPSEG_USAGE
  3. where tablespace = 'TEMP';
  1. select tablespace, username, count(*)
  2. from V$TEMPSEG_USAGE
  3. where 1 = 1
  4. --and tablespace in ('TEMP', 'TEMP02')
  5. --and tablespace = 'TEMP'
  6. group by tablespace, username;

Issue: Shrinking of Temp Tablespace does not take effect

Run this query to find if there are any sessions using your temp tablespace a long time:
  1. SELECT se.username username,
  2. se.SID sid, se.serial# serial#,
  3. se.status status,
  4. 'alter system kill session ''' || se.sid || ',' || se.serial# || ''' immediate;' kill_session_cmd,
  5. se.sql_hash_value, se.sql_id,
  6. se.prev_hash_value,se.machine machine,
  7. su.TABLESPACE tablespace,su.segtype,
  8. su.CONTENTS CONTENTS
  9. FROM v$session se,
  10. v$tempseg_usage su /* v$sort_usage */
  11. WHERE se.saddr=su.session_addr
  12. AND status = 'ACTIVE'
  13. ;
Check if you can drop those sessions and then try shrink. Or you can create a new tablespace move every user to that temp tablespace and than drop this old one.

Move Flash Recovery Area to a new location

For to accomplish moving flash recovery area:
  1. Change the value of the DB_RECOVERY_FILE_DEST initialization parameter to a new value.
  2. Shut down the instance.
  3. Start up the instance and mount the database.
  4. Execute the ALTER DATABASE FLASHBACK OFF command.
  5. Execute the ALTER DATABASE FLASHBACK ON command.
  6. Open the database.

SQL> ALTER SYSTEM SET DB_RECOVERY_FILE_DEST= '/u01/oradata/flash';

SQL>  SHUTDOWN IMMEDIATE;

SQL> STARTUP MOUNT;

SQL> ALTER DATABASE FLASHBACK OFF;

SQL> ALTER DATABASE FLASHBACK ON;

SQL> ALTER DATABASE OPEN;

Use Data Recovery Advisor to Perform Recovery

  1. rman target /
  2. LIST FAILURE;
  3. LIST FAILURE 182 DETAIL;
  4. ADVISE FAILURE;
  5. REPAIR FAILURE;


  • LIST FAILURE - to show information about the failures.
  • ADVISE FAILURE - to obtain a report of your repair options.
  • Finally, REPAIR FAILURE will fix the problem.