Quantcast
Channel: Andrew's Oracle Blog
Viewing all 330 articles
Browse latest View live

Read Only Tables

$
0
0
Oracle 11 introduced a new ALTER TABLE syntax, which allows you to make a table READ ONLY, so I decided to try it out. First I created a table:

SQL> create table table_list
  2  as select table_name from dba_tables
  3  /
 
Table created.

SQL>

... then I made it READ ONLY:
 
SQL> alter table table_list read only
  2  /
 
Table altered.

... so when I tried to update it, Oracle gave me an error:
 
SQL> update table_list
  2  set table_name = 'BLAH'
  3  /
update table_list
       *
ERROR at line 1:
ORA-12081: update operation not allowed on table
"ORACLE"."TABLE_LIST" 

SQL>

I changed the table back to READ WRITE mode like this: 
 
SQL> alter table table_list read write
  2  /
 
Table altered.

SQL>

... then I was able to update it:
 
SQL> update table_list
  2  set table_name = 'BLAH'
  3  /
 
3081 rows updated.
 
SQL>

When you create a table, it is in READ WRITE mode by default. If you try to make it READ WRITE again, you get an error. Once a table is in READ ONLY mode, you get an error if you try to make it READ ONLY again. I checked this out as follows:

SQL> create table andrew (col1 varchar2(1))
  2  /

Table created.

SQL> alter table andrew read write
  2  /
alter table andrew read write
*
ERROR at line 1:
ORA-14140: table ORACLE.ANDREW is already in
read/write mode

SQL> alter table andrew read only
  2  /

Table altered.

SQL> alter table andrew read only
  2  /
alter table andrew read only
*
ERROR at line 1:
ORA-14139: table ORACLE.ANDREW is already in read-only
mode

SQL>


DBMS_MONITOR.SESSION_TRACE_ENABLE

$
0
0
This happened on Oracle 11.2. I had a problem with a 3rd party application hosted in the UK with users in another country. The front-end application was failing regularly with ORA-01426. I needed to know which SQL was causing these errors. First I logged into a test database as user ORACLE:
 
SQL> show user
USER is "ORACLE"
SQL>
 
Then I started a trace of this session as follows:
 
SQL> show user
USER is "SYS"
SQL> select sid, serial# from v$session
  2  where username = 'ORACLE'
  3  /
 
       SID    SERIAL#
---------- ----------
       102       1354
 
SQL> exec dbms_monitor.session_trace_enable(102,1354);
 
PL/SQL procedure successfully completed.
 
SQL>
 
I ran some SQL to produce an ORA-01426 in the traced session:
 
SQL> show user
USER is "ORACLE"
SQL> select power(70,70) from dual
  2  /
select power(70,70) from dual
       *
ERROR at line 1:
ORA-01426: numeric overflow
 
SQL>
 
Then I stopped the trace:
 
SQL> show user
USER is "SYS"
SQL> exec dbms_monitor.session_trace_disable(102,1354);
 
PL/SQL procedure successfully completed.
 
SQL>
 
… but when I looked for the statement in the trace file, I could see no mention of the ORA-01426:
 
=====================
PARSING IN CURSOR #2 len=29 dep=0 uid=8354 oct=3 lid=8354 tim=31182397151149 hv=1978710958 ad='397d685b0' sqlid='0c4sm5duz1fxf'
select power(70,70) from dual
END OF STMT
PARSE #2:c=0,e=217,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1546270724,tim=31182397151146
EXEC #2:c=0,e=403,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1546270724,tim=31182397532682
WAIT #2: nam='SQL*Net message to client' ela= 12 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=31182397532829
FETCH #2:c=0,e=199,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1546270724,tim=31182397533145
STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL  (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
=====================
 
I had hoped that I would be able to trace the application, search the trace file(s) for the ORA-01426 and thus identify the failing SQL but it looks as if I will need to try something else. More to follow…

Integer Arithmetic

$
0
0
I was looking at the problem of the 3rd party application which is generating ORA-01426 errors when I found the following on My Oracle Support. According to Oracle, this issue affects version 11.2.0.4 and above but I tested it on Oracle 11.2.0.1. Since version 10g, Oracle has used integer arithmetic when it can. The largest integer result it can hold is not very long so you can easily get an ORA-01426:
 
SQL> declare
  2   z number;
  3  begin
  4   z := 654321 * -123456;
  5   dbms_output.put_line('z = '||z);
  6  end;
  7  /
declare
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 4
 
SQL>
 
If you add a digit after the decimal point in one of the operands, Oracle thinks that the number is not an integer and the calculation works correctly:
 
SQL> declare
  2   z number;
  3  begin
  4   z := 654321.0 * -123456;
  5   dbms_output.put_line('z = '||z);
  6  end;
  7  /
z = -80779853376
 
PL/SQL procedure successfully completed.
 
SQL>
 
It also works if the integer values are stored in variables:
 
SQL> declare
  2   x number;
  3   y number;
  4   z number;
  5  begin
  6   x := 654321;
  7   y := -123456;
  8   z := x * y;
  9   dbms_output.put_line('z = '||z);
10  end;
11  /
z = -80779853376
 
PL/SQL procedure successfully completed.
 
SQL>
 
Oracle do not regard this as a bug.

Somehow I doubt if this is the cause of my problem as it only seems to manifest itself with hard coded values but I will be bearing it in mind. More to follow...


MDSYS.SDO_COORD_AXES

$
0
0
This was tested on Oracle 11.2. If you need to look at the ORDER column in the above-mentioned table, there only seems to be one way to do it i.e. in upper case and surrounded by double quotes as shown below. I guess this is because ORDER is a reserved word:
 
SQL> desc mdsys.sdo_coord_axes
Name                       Null?    Type
-------------------------- -------- ------------------
COORD_SYS_ID               NOT NULL NUMBER(10)
COORD_AXIS_NAME_ID                  NUMBER(10)
COORD_AXIS_ORIENTATION              VARCHAR2(24)
COORD_AXIS_ABBREVIATION             VARCHAR2(24)
UOM_ID                              NUMBER(10)
ORDER                      NOT NULL NUMBER(5)
 
SQL> select max(order) from mdsys.sdo_coord_axes
  2  /
select max(order) from mdsys.sdo_coord_axes
           *
ERROR at line 1:
ORA-00936: missing expression
 
SQL> select max("order") from mdsys.sdo_coord_axes
  2  /
select max("order") from mdsys.sdo_coord_axes
           *
ERROR at line 1:
ORA-00904: "order": invalid identifier
 
SQL> select max(ORDER) from mdsys.sdo_coord_axes
  2  /
select max(ORDER) from mdsys.sdo_coord_axes
           *
ERROR at line 1:
ORA-00936: missing expression
 
SQL> select max("ORDER") from mdsys.sdo_coord_axes
  2  /
 
MAX("ORDER")
------------
           3
 
SQL>


1 + NULL = NULL

$
0
0
If you try to add a null to a number, the result is a null. You can see what I mean in the example below, which I tested in Oracle 10:
 
SQL> select 1 from dual
  2  /
 
         1
----------
         1
 
SQL> select nvl(null,'null') from dual
  2  /
 
NVL(NULL,'NULL')
----------------
null
 
SQL> select nvl(to_char(1+null),'null') from dual
  2  /
 
NVL(TO_CHAR(1+NULL),'NULL')
---------------------------
null
 
SQL>

DBA_FEATURE_USAGE_STATISTICS

$
0
0
Oracle introduced this view in version 10. It looks like this in version 11:
 
SQL> desc dba_feature_usage_statistics
Name                       Null?    Type
-------------------------- -------- ------------------
DBID                       NOT NULL NUMBER
NAME                       NOT NULL VARCHAR2(64)
VERSION                    NOT NULL VARCHAR2(17)
DETECTED_USAGES            NOT NULL NUMBER
TOTAL_SAMPLES              NOT NULL NUMBER
CURRENTLY_USED                      VARCHAR2(5)
FIRST_USAGE_DATE                    DATE
LAST_USAGE_DATE                     DATE
AUX_COUNT                           NUMBER
FEATURE_INFO                        CLOB
LAST_SAMPLE_DATE                    DATE
LAST_SAMPLE_PERIOD                  NUMBER
SAMPLE_INTERVAL                     NUMBER
DESCRIPTION                         VARCHAR2(128)
 
SQL>
 
As its name suggests, it allows you to see if a database uses a particular Oracle feature or not. In Oracle 11, it has over 150 entries:
 
SQL> l
  1  select count(*)
  2* from dba_feature_usage_statistics
SQL> /
 
  COUNT(*)
----------
       152
 
SQL>
 
Some of the features reported are shown below:
 
SQL> l
  1* select name from dba_feature_usage_statistics
SQL> /
 
 
NAME
-------------------------------------------------------
Encrypted Tablespaces
MTTR Advisor
Multiple Block Sizes
OLAP - Analytic Workspaces
OLAP - Cubes
Oracle Managed Files
Oracle Secure Backup
Parallel SQL DDL Execution
Parallel SQL DML Execution
Parallel SQL Query Execution
Partitioning (system)
Partitioning (user)
Oracle Text
PL/SQL Native Compilation
Real Application Clusters (RAC)
Recovery Area
Recovery Manager (RMAN)
RMAN - Disk Backup
RMAN - Tape Backup
Etc
 
I checked in a database where I did not think that SQL Loader had been used with the Direct Path option. The value in the DETECTED_USAGES column was zero:
 
SQL> l
  1  select detected_usages
  2  from dba_feature_usage_statistics
  3  where name =
  4* 'Oracle Utility SQL Loader (Direct Path Load)'
SQL> /
 
DETECTED_USAGES
---------------
              0
 
SQL>
 
I checked in a database where I had used SQL Loader with the Direct Path option a few times. The value in the DETECTED_USAGES column seemed far too high:
 
SQL> l
  1  select detected_usages
  2  from dba_feature_usage_statistics
  3  where name =
  4* 'Oracle Utility SQL Loader (Direct Path Load)'
SQL> /
 
DETECTED_USAGES
---------------
            231
 
SQL>
 
I will do some research and once I know how this figure is calculated, I will return to this post and update it.

kgxgncin: CLSS init failed with status 3

$
0
0
I had a problem with an Oracle 11.1.0.6.0 database producing trace files every few minutes. Here is one of them:
 
Trace file /oracle/app/oracle/product/diag/rdbms/ecopwpr1/ECOPWPR1/trace/ECOPWPR1_ora_15634.trc
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /oracle/app/oracle/product/11.1.0
System name:    SunOS
Node name:      sge-mktred-spo2
Release:        5.10
Version:        Generic_142900-09
Machine:        sun4u
Instance name: ECOPWPR1
Redo thread mounted by this instance: 1
Oracle process number: 58
Unix process pid: 15634, image: oracle@sge-mktred-spo2
 
*** 2014-07-08 10:18:36.261
*** SESSION ID:(99.22383) 2014-07-08 10:18:36.261
*** CLIENT ID:() 2014-07-08 10:18:36.261
*** SERVICE NAME:(SYS$USERS) 2014-07-08 10:18:36.261
*** MODULE NAME:(JDBC Thin Client) 2014-07-08 10:18:36.261
*** ACTION NAME:() 2014-07-08 10:18:36.261
 
clsc_connect: (109c5b200) no listener at (ADDRESS=(PROTOCOL=ipc)(KEY=OCSSD_LL_sge-mktred-spo2_))
2014-07-08 10:18:36.261: [ CSSCLNT]clsssInitNative: failed to connect to (ADDRESS=(PROTOCOL=ipc)(KEY=OCSSD_LL_sge-mktred-spo2_)), rc 9
kgxgncin: CLSS init failed with status 3
 
I looked for the session afterwards but it had gone:
 
SQL> l
  1  select username from v$session
  2* where sid = 99 and serial# = 22383
SQL> /
 
no rows selected
 
SQL>
 
I started tracing all sessions in the database:
 
SQL> alter system set sql_trace = true
  2  /
 
System altered.
 
SQL>
 
I saw that the trace file directory was quickly filling up with large files so I did the following:
 
SQL> l
  1  alter system
  2* set max_dump_file_size = '1M'
SQL> /
 
System altered.
 
SQL>
 
N.B. If you just give a numeric value without a K or M suffix then Oracle interprets it as a number of operating system blocks so you need to be careful with this parameter.
 
I repeated the following command in the trace file directory every few seconds:
 
Solaris >
grep "kgxgncin: CLSS init failed with status 3" *trc
Solaris >
 
… until a trace file appeared with the error (I didn’t have to wait for long):
 
Solaris > grep "kgxgncin: CLSS init failed with status 3" *trc
ECOPWPR1_ora_23488.trc:kgxgncin: CLSS init failed with status 3
Solaris >
 
I stopped tracing sessions:
 
SQL> alter system set sql_trace = false;
 
System altered.
 
SQL>
 
I looked in the trace file and saw that the error was being produced by the following SQL:
 
=====================
PARSING IN CURSOR #4 len=73 dep=0 uid=76 oct=3 lid=76 tim=2030251677801 hv=3508623573 ad='3af1e7140' sqlid='f25dysg8k2q6p'
select GROUP_NUMBER,NAME,STATE,TYPE,TOTAL_MB,FREE_MB from V$ASM_DISKGROUP
END OF STMT
PARSE #4:c=0,e=104,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=2030251677798
EXEC #4:c=0,e=66,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=2030251677969
clsc_connect: (109c5f460) no listener at (ADDRESS=(PROTOCOL=ipc)(KEY=OCSSD_LL_sge-mktred-spo2_))
2014-07-08 11:05:25.293: [ CSSCLNT]clsssInitNative: failed to connect to (ADDRESS=(PROTOCOL=ipc)(KEY=OCSSD_LL_sge-mktred-spo2_)), rc 9
kgxgncin: CLSS init failed with status 3
FETCH #4:c=10000,e=7591,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=2030251686303
STAT #4 id=1 cnt=0 pid=0 pos=1 obj=0 op='FIXED TABLE FULL X$KFGRP (cr=0 pr=0 pw=0 time=0 us cost=0 size=95 card=1)'
=====================
 
I looked for the username in the trace file but could not see it so I found it like this:
 
SQL> l
  1  select parsing_schema_name
  2  from v$sql
  3* where sql_text = 'select GROUP_NUMBER,NAME,STATE,TYPE,TOTAL_MB,FREE_MB from V$ASM_DISKGROUP'
SQL> /
 
PARSING_SCHEMA_NAME
------------------------------
OEMGRIDDBA
OEMGRIDDBA
 
SQL>
 
I realized it might be difficult to change the SQL which Oracle Enterprise Manager runs. I confirmed that I could reproduce the problem by running the SQL in a stand-alone SQL*Plus session both in the database concerned and in two other Oracle 11.1.0.6 databases. I confirmed that I could NOT reproduce the problem in an Oracle 11.2.0.1 database so I assumed that it was caused by an Oracle bug. To work around the problem, I set up a job to delete these trace files after a few days.  

A Simple Example with Indexes

$
0
0
I did this worked example on Oracle 11.2. First I created a table:

SQL> create table t1
  2  as select * from dba_segments
  3  /
 
Table created.
 
SQL>
 
…then I made sure it contained enough data:
 
SQL> begin
  2  for a in 1..8 loop
  3  insert into t1 select * from t1;
  4  end loop;
  5  end;
  6  /
 
PL/SQL procedure successfully completed.
 
SQL>

I added an index:

SQL> create index i1 on t1(owner, extents)
  2  /
 
Index created.
 
SQL> exec dbms_stats.gather_table_stats -
> (ownname=>'ORACLE',tabname=>'T1');
 
PL/SQL procedure successfully completed.
 
SQL>
 
…then I ran a query against the table:
 
SQL> set autotrace on
SQL> set timing on
SQL> select sum(bytes) from t1
  2  where owner = 'SYS'
  3  and extents = 1
  4  /
 
SUM(BYTES)
----------
3.0098E+10
 
Elapsed: 00:00:27.29
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3693069535
 
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    16 |  2438  (29)| 00:00:03 |
|   1 |  SORT AGGREGATE    |      |     1 |    16 |            |          |
|*  2 |   TABLE ACCESS FULL| T1   | 10388 |   162K|  2438  (29)| 00:00:03 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter("EXTENTS"=1 AND "OWNER"='SYS')
 
 
Statistics
----------------------------------------------------------
        365  recursive calls
          0  db block gets
      37109  consistent gets
      37046  physical reads
          0  redo size
        533  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
          1  rows processed
 
SQL> set autotrace off
SQL> set timing off
SQL>
 
The query had to look at 23% of the rows in the table:
 
SQL> l
  1  select round
  2  ((select count(*) from t1
  3    where owner = 'SYS' and extents = 1)
  4  /
  5  (select count(*) from t1) * 100)
  6* as percentage from dual
SQL> /
 
PERCENTAGE
----------
        23
 
SQL>
 
…so it did a full table scan instead of using the index and the elapsed time was 27 seconds. I wanted to improve on this so I added the bytes column to the index:
 
SQL> drop index i1
  2  /
 
Index dropped.
 
SQL> create index i2 on t1(owner, extents, bytes)
  2  /
 
Index created.
 
SQL> exec dbms_stats.gather_table_stats -
> (ownname=>'ORACLE',tabname=>'T1');
 
PL/SQL procedure successfully completed.
 
SQL>
 
I ran the query again. This time, Oracle could get all the information it needed from the index so the elapsed time went down to 3 seconds:
 
SQL> set autotrace on
SQL> set timing on
SQL> select sum(bytes) from t1
  2  where owner = 'SYS'
  3  and extents = 1
  4  /
 
SUM(BYTES)
----------
3.0098E+10
 
Elapsed: 00:00:03.34
 
Execution Plan
----------------------------------------------------------
Plan hash value: 494139663
 
------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |    16 |   581  (47)| 00:00:01 |
|   1 |  SORT AGGREGATE       |      |     1 |    16 |            |          |
|*  2 |   INDEX FAST FULL SCAN| I2   |   518K|  8099K|   581  (47)| 00:00:01 |
------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter("OWNER"='SYS' AND "EXTENTS"=1)
 
 
Statistics
----------------------------------------------------------
        432  recursive calls
          0  db block gets
       6843  consistent gets
        569  physical reads
          0  redo size
        533  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         13  sorts (memory)
          0  sorts (disk)
          1  rows processed
 
SQL> set autotrace off
SQL> set timing off
SQL>
 
I got the idea for this example in the book below, written by Mark Gurry:


ORA-01460 on PL/SQL Developer

$
0
0
An Oracle 9 database had the following character set:
 
SQL> l
  1  select sys_context('userenv','LANGUAGE')
  2* from dual
SQL> /
 
SYS_CONTEXT('USERENV','LANGUAGE')
----------------------------------------
ENGLISH_UNITED KINGDOM.WE8ISO8859P15
 
SQL>
 
I used PL/SQL Developer to look at the code in the database (as usual, click on the image to enlarge it and bring it into focus):

 
Somebody typed the following command in the database by mistake:
 
SQL> l
  1* create database sonar character set utf8
SQL> /
create database sonar character set utf8
*
ERROR at line 1:
ORA-01031: insufficient privileges
 
SQL>
 
I logged in to PL/SQL Developer again and found that I got an ORA-01460 when I tried to look at the same code in the database:


I also noticed that the database had a new character set:
 
SQL> l
  1  select sys_context('userenv','LANGUAGE')
  2* from dual
SQL> /
 
SYS_CONTEXT('USERENV','LANGUAGE')
----------------------------------------
ENGLISH_UNITED KINGDOM.UTF8
 
SQL>

I guess this is a bug as the user account which typed the create database command had no special privileges and Oracle replied with an ORA-01031. Therefore no damage should have been caused.

Three days later:

I logged in as a privileged user and tried to change the character set back but this failed, in line with the Oracle documentation:

SQL> conn / as sysdba
Connected.
SQL> alter database character set we8iso8859p15
  2  /
alter database character set we8iso8859p15
*
ERROR at line 1:
ORA-12712: new character set must be a superset of old character set
 
SQL>
 
So, as a last resort, I logged back in with an ordinary user and tried to reverse the damage like this:
 
SQL> conn andrew/reid
Connected.
SQL> create database sonar character set we8iso8859p15
  2  /
create database sonar character set we8iso8859p15
*
ERROR at line 1:
ORA-01031: insufficient privileges
 
SQL>
 
This seemed to have the desired effect, at least in the short term as the character set went back to its original value:
 
SQL> select sys_context('userenv','LANGUAGE')
  2  from dual
  3  /
 
SYS_CONTEXT('USERENV','LANGUAGE')
--------------------------------------------------------------------------------
AMERICAN_AMERICA.WE8ISO8859P15
 
SQL>
 
I will report back as the problem develops…

FIXED_DATE and LAST_ANALYZED

$
0
0
I tested this on Oracle 11.2.0.1. You need to be careful when looking at the LAST_ANALYZED column in USER_TABLES. I created a table and removed the FIXED_DATE parameter from the database:
 
SQL> create table t1 (c1 number)
  2  /
 
Table created.
 
SQL> alter system set fixed_date = none
  2  /
 
System altered.
 
SQL>
 
…then I used DBMS_STATS.GATHER_TABLE_STATS and the old ANALYZE command to create statistics for the table. Both of them set the LAST_ANALYZED column in USER_TABLES to the current date:
 
SQL> exec dbms_stats.gather_table_stats -
> (ownname=>'ORACLE',tabname=>'T1');
 
PL/SQL procedure successfully completed.
 
SQL> select last_analyzed
  2  from user_tables
  3  where table_name = 'T1'
  4  /
 
LAST_ANALYZED
-------------
10-SEP-14
 
SQL> analyze table t1 compute statistics
  2  /
 
Table analyzed.
 
SQL> select last_analyzed
  2  from user_tables
  3  where table_name = 'T1'
  4  /
 
LAST_ANALYZED
-------------
10-SEP-14
 
SQL>
 
I set FIXED_DATE to 25th December 2014 and tried again:
 
SQL> alter system set fixed_date = '25-DEC-2014'
  2  /
 
System altered.
 
SQL>
 
DBMS_STATS.GATHER_TABLE_STATS set the LAST_ANALYZED column to the new FIXED_DATE value. I believe this is not what Oracle intended and may be a result of bug 8892343, which states:
 
The value of the LAST_ANALYZED column in USER_TABLES views is affected by the setting of the FIXED_DATE parameter when it should be independent of that value.
 
SQL> exec dbms_stats.gather_table_stats -
> (ownname=>'ORACLE',tabname=>'T1');
 
PL/SQL procedure successfully completed.
 
SQL> select last_analyzed
  2  from user_tables
  3  where table_name = 'T1'
  4  /
 
LAST_ANALYZED
-------------
25-DEC-14
 
SQL>
 
…whereas the old ANALYZE command set the LAST_ANALYZED column to the underlying system date:
 
SQL> analyze table t1 compute statistics
  2  /
 
Table analyzed.
 
SQL> select last_analyzed
  2  from user_tables
  3  where table_name = 'T1'
  4  /
 
LAST_ANALYZED
-------------
10-SEP-14
 
SQL>

How to See When Your Database Was Opened

$
0
0
This was tested on Oracle 11.2: 

SQL> l
  1* select startup_time from v$instance
SQL> /
 
STARTUP_TIME
------------
24-MAY-12
 
SQL>


ORA-01123

$
0
0
I was reading through an old book recently and it said that you could not put a tablespace into hot backup mode if the database was in NOARCHIVELOG mode. This seemed reasonable to me but I wondered what might happen if you tried to do this so I ran the following SQL in an Oracle 11.2 database:  

SQL> l
  1* alter tablespace users begin backup
SQL> /
alter tablespace users begin backup
*
ERROR at line 1:
ORA-01123: cannot start online backup; media recovery
not enabled
 
SQL>

If this happens to you, you have two choices:
  •  Don't do it again OR
  • Put the database into ARCHIVELOG mode first.
I hope to be doing some more serious posts about hot backup and recovery in the near future.

PASSWORD_REUSE_MAX and PASSWORD_REUSE_TIME

$
0
0
I tested this on Oracle 11.2. I created a profile called FOR_ANDREW with PASSWORD_REUSE_MAX set to 1. This meant that I could not reuse a password until I had used one other password first:
 
SQL> conn / as sysdba
Connected.
 
SQL> create profile for_andrew
  2  limit password_reuse_max 1
  3  /
 
Profile created.
 
SQL>
 
I created a user called ANDREW and gave him the FOR_ANDREW profile:
 
SQL> create user andrew
  2  identified by old_password
  3  profile for_andrew
  4  /
 
User created.
 
SQL> grant create session to andrew
  2  /
 
Grant succeeded.
 
SQL>
 
I connected to the database as user ANDREW:
 
SQL> conn andrew/old_password
Connected.
SQL>
 
I tried to reuse the existing password but this failed as I had expected it would:
 
SQL> alter user andrew
  2  identified by old_password
  3  /
alter user andrew
*
ERROR at line 1:
ORA-28007: the password cannot be reused
 
SQL>
 
I used a different password before trying to reuse the original one. This failed with the same error, which I had not expected:
 
SQL> alter user andrew
  2  identified by new_password
  3  /
 
User altered.
 
SQL> alter user andrew
  2  identified by old_password
  3  /
alter user andrew
*
ERROR at line 1:
ORA-28007: the password cannot be reused
 
SQL>
 
I did some research and saw that the PASSWORD_REUSE_TIME was set to DEFAULT. This meant that it had the same value as the DEFAULT profile where it was set to UNLIMITED:
 
SQL> conn / as sysdba
Connected.
SQL> select limit from dba_profiles
  2  where profile = 'FOR_ANDREW'
  3  and resource_name = 'PASSWORD_REUSE_TIME'
  4  /
 
LIMIT
----------------------------------------
DEFAULT
 
SQL> select limit from dba_profiles
  2  where profile = 'DEFAULT'
  3  and resource_name = 'PASSWORD_REUSE_TIME'
  4  /
 
LIMIT
----------------------------------------
UNLIMITED
 
SQL>
 
According to the Oracle 11.1 documentation:
 
These two parameters must be set in conjunction with each other. PASSWORD_REUSE_TIME specifies the number of days before which a password cannot be reused. PASSWORD_REUSE_MAX specifies the number of password changes required before the current password can be reused.
 
It then went on to say:

For these parameter to have any effect, you must specify an integer for both of them. 

... which I found a bit misleading. However, it clarified this a few lines later as follows: 

If you specify an integer for either of these parameters and specify UNLIMITED for the other, then the user can never reuse a password. 

I set PASSWORD_REUSE_TIME to 1 minute and checked that I still could not reinstate the original password:

SQL> alter profile for_andrew
  2  limit password_reuse_time 1/1440
  3  /
 
Profile altered.
 
SQL> conn andrew/new_password
Connected.
SQL> alter user andrew
  2  identified by old_password
  3  /
alter user andrew
*
ERROR at line 1:
ORA-28007: the password cannot be reused
 
SQL>
 
However, I waited for a minute and found that I could:
 
SQL> exec sys.dbms_lock.sleep(60);
 
PL/SQL procedure successfully completed.
 
SQL> alter user andrew
  2  identified by old_password
  3  /
 
User altered.
 
SQL>
 
I do not know which Oracle process controls this functionality but it seemed a bit hit and miss. When I repeated the test, I sometimes found I had to wait more than a minute before I could change the password back to its original value. 

OPTIMIZER_MODE = FIRST_ROWS_N

$
0
0
I have known about the first_rows optimizer mode for some time. This tells Oracle to use an execution path which will return the first few rows as quickly as possible. However, I recently read about the first_rows_n optimizer mode, which apparently appeared first in Oracle 9. This tells Oracle to use an execution path which will return the first n rows quickly, where n can be 1, 10, 100 or 1000. I decided to try it out in an Oracle 11.2 database. First I checked that Oracle would accept the expected values of n:

SQL> alter session set optimizer_mode = first_rows
  2  /
 
Session altered.
 
SQL> alter session set optimizer_mode = first_rows_1
  2  /
 
Session altered.
 
SQL> alter session set optimizer_mode = first_rows_10
  2  /
 
Session altered.
 
SQL> alter session set optimizer_mode = first_rows_100
  2  /
 
Session altered.
 
SQL>

…then, before checking the final option, I started to trace my SQL*Plus session:

SQL> alter session set sql_trace = true
  2  /
 
Session altered.
 
SQL> alter session set optimizer_mode = first_rows_1000
  2  /
 
Session altered.
 
SQL> select sysdate "first_rows_1000" from dual
  2  /
 
first_rows_1000
---------------
29-SEP-14
 
SQL> alter session set sql_trace = false
  2  /
 
Session altered.
 
SQL>

I ran the trace file through tkprof and looked at the explain plan for the query I had just run. It did not seem to be aware exactly which optimizer mode I had used: 

********************************************************************************
 
SQL ID: 9u1zkyyn9vbt4
Plan Hash: 1546270724
select sysdate "first_rows_1000"
from
dual
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.01       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        4      0.00       0.00          0          0          0           2
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        8      0.01       0.00          0          0          0           2
 
Misses in library cache during parse: 1
Optimizer mode: FIRST_ROWS
Parsing user id: 5  (SYSTEM)
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  FAST DUAL  (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)
 
 
Rows     Execution Plan
-------  ---------------------------------------------------
      0  SELECT STATEMENT   MODE: FIRST_ROWS
      1   FAST DUAL
 
********************************************************************************
 
Finally, I tried to use an invalid value for n. This time the error message explained exactly where I had gone wrong: 

SQL> alter session set optimizer_mode = first_rows_99
  2  /
ERROR:
ORA-00096: invalid value FIRST_ROWS_99 for parameter
optimizer_mode, must be from among first_rows_1000,
first_rows_100, first_rows_10, first_rows_1,
first_rows, all_rows, choose, rule
SQL>

Bug 5497611

$
0
0
I used Oracle Enterprise Manager to look at the execution plan for some SQL in an Oracle 10.2.0.3 database. (The SQL shown is just an example done later for the purposes of this blog post. As usual, click on the image to enlarge it and bring it into focus if necessary.):


This produced the following ORA-00600 message several times in the alert log:
 
Wed Oct  1 18:13:21 2014
Errors in file /oracle/app/oracle/product/10.2.0/admin/mrmdpt1/udump/mrmdpt1_ora_15467.trc:
ORA-00600: internal error code, arguments: [qctVCO:csform], [0], [0], [0], [0], [112], [2], [224]
 
I looked in the trace file and saw the SQL which had caused the problem:
 
ORA-00600: internal error code, arguments: [qctVCO:csform], [0], [0], [0], [0], [112], [2], [224]
Current SQL statement for this session:
SELECT extractvalue(xmlval, '/*/info[@type = "sql_profile"]'), extractvalue(xmlval, '/*/info[@type = "outline"]'), extractvalue(xmlval, '/*/info[@type = "dyn
amic_sampling"]'), nvl(extractvalue(xmlval, '/*/info[@type = "index_size"]'), -1) from (select xmltype(other_xml) xmlval from v$sql_plan where sql_id = :1 an
d other_xml is not null and id = 1)

I extracted the SQL and ran it in a SQL*Plus session:

SQL> set head off
SQL> l
  1  SELECT
  2  extractvalue(xmlval, '/*/info[@type = "sql_profile"]'),
  3  extractvalue(xmlval, '/*/info[@type = "outline"]'),
  4  extractvalue(xmlval, '/*/info[@type = "dynamic_sampling"]'),
  5  nvl(extractvalue(xmlval, '/*/info[@type = "index_size"]'), -1)
  6  from
  7  (select xmltype(other_xml) xmlval
  8   from v$sql_plan
  9   where sql_id = 'cp5caasd2udnw'
 10   and other_xml is not null
 11*  and id = 1)
SQL> /
 
 
 
 
-1
 
 
 
 
-1
 
 
SQL>
 
Each time I did this, a similar ORA-00600 appeared in the alert log, proving that I had correctly diagnosed the cause of the problem. I looked the problem up in My Oracle Support and found that it was caused by bug 5497611.

ORA-02391

$
0
0
I tested this on an Oracle 11.1 database.
 
Oracle profiles control how certain database resources are allocated to a user session. They also define some security rules. When you create a user, it is assigned a profile and, if you do not specify it explicitly, the DEFAULT profile will be used:
 
SQL> grant create session to andrew
  2  identified by reid
  3  /
 
Grant succeeded.
 
SQL> select profile from dba_users
  2  where username = 'ANDREW'
  3  /
 
PROFILE
------------------------------
DEFAULT
 
SQL>
 
You can look at the limits defined in a profile by querying DBA_PROFILES:
 
SQL> select profile, resource_name, limit
  2  from dba_profiles
  3  where profile = 'DEFAULT'
  4  and resource_name = 'SESSIONS_PER_USER'
  5  /
 
PROFILE    RESOURCE_NAME        LIMIT
---------- -------------------- ----------
DEFAULT    SESSIONS_PER_USER    UNLIMITED
 
SQL>
 
The SESSIONS_PER_USER resource is set to UNLIMITED so a user with the DEFAULT profile can have as many simultaneous sessions as he wishes. What can you do if you do not like this? You can create a new profile with a different SESSIONS_PER_USER limit and assign it to the user. I will demonstrate this in a future post. Alternatively you can alter the DEFAULT profile, as shown below:
 
SQL> alter profile default
  2  limit sessions_per_user 3
  3  /
 
Profile altered.
 
SQL> select profile, resource_name, limit
  2  from dba_profiles
  3  where profile = 'DEFAULT'
  4  and resource_name = 'SESSIONS_PER_USER'
  5  /
 
PROFILE    RESOURCE_NAME        LIMIT
---------- -------------------- ----------
DEFAULT    SESSIONS_PER_USER    3
 
SQL>
 
You also need to set RESOURCE_LIMIT to TRUE otherwise Oracle does not check limits in a user's profile at all:
 
SQL> alter system set resource_limit = true
  2  /
 
System altered.
 
SQL>
 
The screen print below shows how this works (as usual, click on the image to enlarge it and bring it into focus if necessary).Three simultaneous connections have been made to the database. A fourth connection is then attempted but fails with an ORA-02391:


Worked Examples with the SET ROLE Command

$
0
0
Before I start, I wonder if anybody can help me. Some time ago, I saw several adverts on the Internet similar to the one below:

I am looking for an Oracle DBA (French speaking) - Hampshire (South Coast of England)

Languages: ENGLISH and FRENCH


We are recruiting for a major blue chip company based in the South of English (Hampshire area), where we seek a proven Oracle Database Administrator (HPUX, Linux, and AIX) who can work well within the team environment (onshore and offshore).


Mainly production support, you will have excellent communication skills and be able to think independently in view of providing Database solutions to the UK and France. Some travel may be required, however with a UK base.


Technical Environment:


Day to Day BAU work on all production Oracle DB's, this includes resolving incidents as they come in and prioritizing work based on systems criticality.

- Support of large multi terabyte SAP databases. Duties include performance tuning, space management, cloning and backups (RMAN and Korn Shell Scripts).
- Installation and configuration of all Oracle (and SQL Server Databases), Oracle Versions 8i-11G, SQL Server 6.5 - 2008 R2, in clustered, replicated, and stand alone environments.
- Developer support for problem solving
- 24/7 on-call support of production environment on a Rota.

Each advert would stay on-line for a while before being replaced by a similar advert run by a different agency. It looked to me as though they were having trouble filling the position. Each time I saw one of these adverts, I wrote to the agency involved but none of them replied. If you know the name of the company who were looking for the French speaking DBA, perhaps you would be kind enough to add a comment at the end of this post?

Now here is today's example:

I tested this on Oracle 11.2. First I created a role:
 
SQL> conn / as sysdba
Connected.
SQL> create role role1
  2  /
 
Role created.
 
SQL> grant select on dba_tables to role1
  2  /
 
Grant succeeded.
 
SQL>
 
Then I created a user and granted the role to him:
 
SQL> create user andrew identified by reid
  2  /
 
User created.
 
SQL> grant create session, role1 to andrew
  2  /
 
Grant succeeded.
 
SQL>
 
The user had this as a default role:
 
SQL> select granted_role, default_role
  2  from dba_role_privs
  3  where grantee = 'ANDREW'
  4  /
 
GRANTED_ROLE DEFAULT_ROLE
------------ ------------
ROLE1        YES
 
SQL>
 
...so when he logged in, it appeared in SESSION_ROLES, which shows the roles you currently have enabled:
 
SQL> conn andrew/reid
Connected.
SQL> select role from session_roles
  2  /
 
ROLE
-----
ROLE1
 
SQL>
 
... and he could use the permissions granted by that role:
 
SQL> select count(*) from dba_tables
  2  /
 
  COUNT(*)
----------
      3149
 
SQL>
 
I changed the user so he had no default roles:
 
SQL> conn / as sysdba
Connected.
SQL> alter user andrew default role none
  2  /
 
User altered.
 
SQL>
 
... so the role was no longer shown as a default role for him in DBA_ROLE_PRIVS:
 
SQL> select granted_role, default_role
  2  from dba_role_privs
  3  where grantee = 'ANDREW'
  4  /
 
GRANTED_ROLE DEFAULT_ROLE
------------ ------------
ROLE1        NO
 
SQL>
 
When he logged in this time, the role did not appear in SESSION_ROLES:
 
SQL> conn andrew/reid
Connected.
SQL> select role from session_roles
  2  /
 
no rows selected
 
SQL>
 
... and he could not use the permissions granted via that role:
 
SQL> select count(*) from dba_tables
  2  /
select count(*) from dba_tables
                     *
ERROR at line 1:
ORA-00942: table or view does not exist
 
SQL>
 
However, he was able to enable the role like this:
 
SQL> set role role1
  2  /
 
Role set.
 
SQL>
 
… and then it appeared in SESSION_ROLES:
 
SQL> select role from session_roles
  2  /
 
ROLE
-----
ROLE1
 
SQL>
 
... and he could use the permissions granted by the role:
 
SQL> select count(*) from dba_tables
  2  /
 
  COUNT(*)
----------
      3149
 
SQL>
 
This has always seemed a bit strange to me, either you want a user to have a role or you don't!
 
Then the user decided he no longer needed the role to be enabled so he removed it from SESSION_ROLES like this:
 
SQL> set role none
  2  /
 
Role set.
 
SQL> select role from session_roles
  2  /
 
no rows selected
 
SQL>
 
Next, I changed the role so it had to be enabled with a password:
 
SQL> conn / as sysdba
Connected.
SQL> alter role role1 identified by secret_password
  2  /
 
Role altered.
 
SQL>
 
...so when the user tried to enable the role, Oracle needed a password. The user did not provide one so Oracle returned an error:
 
SQL> conn andrew/reid
Connected.
SQL> set role role1
  2  /
set role role1
*
ERROR at line 1:
ORA-01979: missing or invalid password for role
'ROLE1'
 
SQL>
 
…and the role did not appear in SESSION_ROLES:
 
SQL> select role from session_roles
  2  /
 
no rows selected
 
SQL>
 
The user tried again, this time including the password:
 
SQL> set role role1 identified by secret_password
  2  /
 
Role set.
 
SQL>
 
The role appeared in SESSION_ROLES:
 
SQL> select role from session_roles
  2  /
 
ROLE
-----
ROLE1
 
SQL>
 
…and the user could look at DBA_TABLES:
 
SQL> select count(*) from dba_tables
  2  /
 
  COUNT(*)
----------
      3149
 
SQL>
 

Bug 8477973

$
0
0
I ran the following query on an Oracle 11.1.0.6 database but it failed with an ORA-02020:
 
SQL> SELECT ppc.sttlmnt_dt day_date
  2  FROM   vrm_d18_ppc   ppc,
  3         meter_nhh     mtr,
  4         mtd_registers reg
  5  WHERE  ppc.tm_pttrn_rgm = reg.tpr
  6  AND    TO_NUMBER(ppc.stndrd_sttlmnt_cnfgrtn_id) = mtr.std_stlmnt_config_id
  7  AND    ppc.prfl_clss_id = mtr.profile_class_id
  8  AND    ppc.gsp_grp_id = mtr.gsp_group_id
  9  AND    reg.mpan_core = mtr.mpan_core
 10  AND    reg.mpan_core = '1900008212269'
 11  AND    mtr.meter_id = 3232
 12  AND    reg.meter_serial_id = 'L8103349'
 13  AND    reg.meter_register_id = 'TO'
 14  AND    ppc.sttlmnt_dt BETWEEN '01-AUG-14' AND '31-AUG-14'
 15  /
ERROR:
ORA-02020: too many database links in use
 
no rows selected
 
SQL>
 
I checked the value of the open_links initialization parameter:
 
SQL> l
  1  select value from v$parameter
  2* where name = 'open_links'
SQL> /
 
VALUE
----------
4
 
SQL>
 
I looked at the execution plan and saw that it accessed several tables down the same database link. It also used nested loops:

********************************************************************************
 
SELECT ppc.sttlmnt_dt day_date
FROM   vrm_d18_ppc   ppc,
       meter_nhh     mtr,
       mtd_registers reg
WHERE  ppc.tm_pttrn_rgm = reg.tpr
AND    TO_NUMBER(ppc.stndrd_sttlmnt_cnfgrtn_id) = mtr.std_stlmnt_config_id
AND    ppc.prfl_clss_id = mtr.profile_class_id
AND    ppc.gsp_grp_id = mtr.gsp_group_id
AND    reg.mpan_core = mtr.mpan_core
AND    reg.mpan_core = '1900008212269'
AND    mtr.meter_id = 3232
AND    reg.meter_serial_id = 'L8103349'
AND    reg.meter_register_id = 'TO'
AND    ppc.sttlmnt_dt BETWEEN '01-AUG-14' AND '31-AUG-14'
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.04       0.19          0          0          1           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.05       0.52          7          8          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.09       0.72          7          8          1           1
 
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 78  (SRCE)
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  FILTER  (cr=7 pr=7 pw=7 time=0 us)
      1   NESTED LOOPS  (cr=7 pr=7 pw=7 time=0 us cost=10 size=216 card=1)
      1    NESTED LOOPS  (cr=7 pr=7 pw=7 time=0 us cost=9 size=190 card=1)
      1     NESTED LOOPS  (cr=3 pr=3 pw=3 time=0 us cost=8 size=156 card=1)
      1      NESTED LOOPS  (cr=3 pr=3 pw=3 time=0 us cost=7 size=139 card=1)
      1       NESTED LOOPS  (cr=3 pr=3 pw=3 time=0 us cost=6 size=125 card=1)
      2        NESTED LOOPS  (cr=3 pr=3 pw=3 time=379976 us cost=5 size=113 card=1)
      2         NESTED LOOPS  (cr=3 pr=3 pw=3 time=255776 us cost=4 size=86 card=1)
      2          NESTED LOOPS  (cr=3 pr=3 pw=3 time=127596 us cost=3 size=66 card=1)
      2           NESTED LOOPS  (cr=3 pr=3 pw=3 time=972 us cost=2 size=40 card=1)
      1            TABLE ACCESS BY INDEX ROWID METER_NHH (cr=3 pr=3 pw=3 time=0 us cost=1 size=23 card=1)
      1             INDEX UNIQUE SCAN METER_NHH_PK (cr=2 pr=2 pw=2 time=0 us cost=1 size=0 card=1)(object id 106394)
      2            REMOTE  D18_780 (cr=0 pr=0 pw=0 time=967 us cost=1 size=17 card=1)
      2           REMOTE  D18_781 (cr=0 pr=0 pw=0 time=0 us cost=1 size=26 card=1)
      2          REMOTE  D18_782 (cr=0 pr=0 pw=0 time=0 us cost=1 size=20 card=1)
      2         REMOTE  D18_783 (cr=0 pr=0 pw=0 time=0 us cost=1 size=27 card=1)
      1        REMOTE  D18_784 (cr=0 pr=0 pw=0 time=0 us cost=1 size=12 card=1)
      1       REMOTE  D18_787 (cr=0 pr=0 pw=0 time=0 us cost=1 size=14 card=1)
      1      REMOTE  D18_789 (cr=0 pr=0 pw=0 time=0 us cost=1 size=17 card=1)
      1     TABLE ACCESS BY INDEX ROWID MTD_REGISTERS (cr=5 pr=4 pw=4 time=0 us cost=1 size=34 card=1)
      1      INDEX RANGE SCAN MR_PK (cr=4 pr=3 pw=3 time=0 us cost=1 size=0 card=1)(object id 106689)
      1    REMOTE  D18_790 (cr=0 pr=0 pw=0 time=0 us cost=1 size=26 card=1)
 
 
Rows     Execution Plan
-------  ---------------------------------------------------
      0  SELECT STATEMENT   MODE: ALL_ROWS
      1   FILTER
      1    NESTED LOOPS
      1     NESTED LOOPS
      1      NESTED LOOPS
      1       NESTED LOOPS
      1        NESTED LOOPS
      2         NESTED LOOPS
      2          NESTED LOOPS
      2           NESTED LOOPS
      2            NESTED LOOPS
      1             TABLE ACCESS   MODE: ANALYZED (BY INDEX
                        ROWID) OF 'METER_NHH' (TABLE)
      1              INDEX   MODE: ANALYZED (UNIQUE SCAN) OF
                         'METER_NHH_PK' (INDEX (UNIQUE))
      2             REMOTE OF 'D18_780' (REMOTE)
                        [PQE_TO_DMV_LINK]
                       SELECT "D18_780_ID","STTLMNT_DT" FROM "DMV"."D18_780"
                       "A" WHERE TO_CHAR("D18_780_ID") LIKE '%' AND
                         "STTLMNT_DT">=:1 AND "STTLMNT_DT"<=:2
      2            REMOTE OF 'D18_781' (REMOTE) [PQE_TO_DMV_LINK]
 
                      SELECT "D18_781_ID","D18_780_ID" FROM "DMV"."D18_781"
                      "B" WHERE TO_CHAR("D18_781_ID") LIKE '%' AND :1=
                        "D18_780_ID"
      2           REMOTE OF 'D18_782' (REMOTE) [PQE_TO_DMV_LINK]
                     SELECT "D18_782_ID","D18_781_ID" FROM "DMV"."D18_782"
                     "C" WHERE TO_CHAR("D18_782_ID") LIKE '%' AND
                       "D18_781_ID"=:1
      2          REMOTE OF 'D18_783' (REMOTE) [PQE_TO_DMV_LINK]
                    SELECT "D18_783_ID","D18_782_ID","GSP_GRP_ID" FROM
                    "DMV"."D18_783""D" WHERE TO_CHAR("D18_783_ID") LIKE
                      '%' AND "GSP_GRP_ID"=:1 AND :2="D18_782_ID"
      1         REMOTE OF 'D18_784' (REMOTE) [PQE_TO_DMV_LINK]
                   SELECT "D18_784_ID","D18_783_ID","PRFL_CLSS_ID" FROM
                   "DMV"."D18_784""E" WHERE TO_CHAR("D18_784_ID") LIKE '%'
                     AND "PRFL_CLSS_ID"=:1 AND "D18_783_ID"=:2
      1        REMOTE OF 'D18_787' (REMOTE) [PQE_TO_DMV_LINK]
                  SELECT "D18_787_ID","D18_784_ID",
                  "STNDRD_STTLMNT_CNFGRTN_ID" FROM "DMV"."D18_787""F"
                  WHERE TO_CHAR("D18_787_ID") LIKE '%' AND
                  TO_NUMBER("STNDRD_STTLMNT_CNFGRTN_ID")=:1 AND :2=
                    "D18_784_ID"
      1       REMOTE OF 'D18_789' (REMOTE) [PQE_TO_DMV_LINK]
                 SELECT "D18_789_ID","D18_787_ID","TM_PTTRN_RGM" FROM
                 "DMV"."D18_789""G" WHERE TO_CHAR("D18_789_ID") LIKE '%'
                   AND :1="D18_787_ID"
      1      TABLE ACCESS   MODE: ANALYZED (BY INDEX ROWID) OF
                 'MTD_REGISTERS' (TABLE)
      1       INDEX   MODE: ANALYZED (RANGE SCAN) OF 'MR_PK' (INDEX
                  (UNIQUE))
      1     REMOTE OF 'D18_790' (REMOTE) [PQE_TO_DMV_LINK]
               SELECT "D18_790_ID","D18_789_ID" FROM "DMV"."D18_790""H"
                 WHERE TO_CHAR("D18_790_ID") LIKE '%' AND "D18_789_ID"=:1
 
********************************************************************************
 
According to My Oracle Support:
              
This issue can appear as a regression introduced in 11.1.0.6 due to improved nested loops code added in 11g.
 
and
 
If a SQL is accessing multiple remote tables at the same remote site then depending on the execution plan chosen it is possible to get multiple database link connections opened when this did not occur in earlier releases. The opening of more than one database link for the SQL can lead to ORA-2020 errors.
 
I increased the value of the open_links parameter:
 
SQL> conn / as sysdba
Connected.
SQL> alter system set open_links = 10
  2  scope = spfile
  3  /
 
System altered.
 
SQL> startup force
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE instance started.
 
Total System Global Area  630702080 bytes
Fixed Size                  2091232 bytes
Variable Size             381687584 bytes
Database Buffers          243269632 bytes
Redo Buffers                3653632 bytes
Database mounted.
Database opened.
SQL> select value from v$parameter
  2  where name = 'open_links'
  3  /
 
VALUE
----------
10
 
SQL>
 
I checked that the query then worked:
 
SQL> SELECT ppc.sttlmnt_dt day_date
  2  FROM   vrm_d18_ppc   ppc,
  3         meter_nhh     mtr,
  4         mtd_registers reg
  5  WHERE  ppc.tm_pttrn_rgm = reg.tpr
  6  AND    TO_NUMBER(ppc.stndrd_sttlmnt_cnfgrtn_id) = mtr.std_stlmnt_config_id
  7  AND    ppc.prfl_clss_id = mtr.profile_class_id
  8  AND    ppc.gsp_grp_id = mtr.gsp_group_id
  9  AND    reg.mpan_core = mtr.mpan_core
10  AND    reg.mpan_core = '1900008212269'
11  AND    mtr.meter_id = 3232
12  AND    reg.meter_serial_id = 'L8103349'
13  AND    reg.meter_register_id = 'TO'
14  AND    ppc.sttlmnt_dt BETWEEN '01-AUG-14' AND '31-AUG-14'
15  /
 
DAY_DATE
---------
01-AUG-14
02-AUG-14
03-AUG-14
04-AUG-14
05-AUG-14
Etc
 
Once the query had finished, I checked the number of links the session had opened:
 
SQL> select db_link from v$dblink
  2  /
 
DB_LINK
--------------------
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
PQE_TO_DMV_LINK
 
8 rows selected.
 
SQL>
 
It should have needed only one, not eight. This is another feature of this bug.
 
I reran the query in a copy of the same database on Oracle 11.2.0.4, which still had its open_links parameter set to the default of four. It ran successfully so I checked the explain plan. It still did as many nested loops but, when I checked the number of links the session had opened, I only saw one so the bug does not appear to affect this version of Oracle:
 
SQL> select db_link from v$dblink
  2  /
 
DB_LINK
--------------------
PQE_TO_DMV_LINK
 
SQL>

How to See the Height of an Index

$
0
0
This example shows where to find the height of an index. I tested it on Oracle 11.2. First I deleted the index's statistics:

SQL> exec dbms_stats.delete_index_stats -
> ('uimsmgr','ubbchst_serv_index');
 
PL/SQL procedure successfully completed.
 
SQL>
 
Then I checked its BLEVEL was null:

SQL> select nvl(blevel,999)
  2  from dba_indexes
  3  where owner = 'UIMSMGR'
  4  and index_name = 'UBBCHST_SERV_INDEX'
  5  /
 
NVL(BLEVEL,999)
---------------
            999
 
SQL>
 
I recalculated the index's statistics:
 
SQL> exec dbms_stats.gather_index_stats -
> ('uimsmgr','ubbchst_serv_index');
 
PL/SQL procedure successfully completed.
 
SQL>
 
After that, the BLEVEL column in DBA_INDEXES showed the index’s height:

SQL> select nvl(blevel,999)
  2  from dba_indexes
  3  where owner = 'UIMSMGR'
  4  and index_name = 'UBBCHST_SERV_INDEX'
  5  /
 
NVL(BLEVEL,999)
---------------
              3
 
SQL>
 
I used to calculate an index's height by analyzing it then looking in INDEX_STATS. First I checked that INDEX_STATS was empty (you will see why I showed the username later):

SQL> select name, height from index_stats
  2  /
 
no rows selected
 
SQL> show user
USER is "ORACLE"
SQL>
 
Then I analyzed the index:

SQL> analyze index uimsmgr.ubbchst_serv_index
  2  validate structure
  3  /
 
Index analyzed.
 
SQL>
 
... and checked its height in INDEX_STATS again. This height comes out as BLEVEL + 1. I guess Oracle starts to count it from a different place as this happened in Oracle 9 too:
 
SQL> select name, height from index_stats
  2  /
 
NAME                               HEIGHT
------------------------------ ----------
UBBCHST_SERV_INDEX                      4
 
SQL>
 
INDEX_STATS is a public synonym for the SYS.INDEX_STATS view. It is far too complicated for me to follow but I know that it never has more than one row, which holds details for the index you analyzed most recently. It is also session specific so, if you start a new session, it will be empty again:
 
SQL> conn / as sysdba
Connected.
SQL> show user
USER is "SYS"
SQL> select name, height from index_stats
  2  /
 
no rows selected
 
SQL>
 
You can read more about this starting on page 69 of the book advertised below:


ORA-02205

$
0
0
I found some notes from a course I took in 1990. They said that it was only possible to GRANT ALTER or GRANT SELECT on a sequence. This seemed reasonable to me but I wanted to check if it was still the case. I did this test on Oracle 12.1. First I created a user who would own a sequence:

SQL> create user u1 identified by pw1
  2  /
 
User created.
 
SQL> grant create session, create sequence to u1
  2  /
 
Grant succeeded.

SQL>

Then I created a user who would be granted access to the sequence:

SQL> create user u2 identified by pw2
  2  /
 
User created.

SQL>

The first user created a sequence then did a GRANT ALL on it to the second user:

SQL> conn u1/pw1
Connected.
SQL> create sequence s1
  2  /
 
Sequence created.
 
SQL> grant all on s1 to u2
  2  /
 
Grant succeeded.

SQL>

I looked for the privileges which had been given to the second user but only found ALTER and SELECT. This confirmed what I had read in my notes:

SQL> select privilege from all_tab_privs
  2  where grantor = 'U1'
  3  and grantee = 'U2'
  4  and table_name = 'S1'
  5  /
 
PRIVILEGE                                             
----------------------------------------              
ALTER                                                 
SELECT

SQL>

Finally I tried to GRANT UPDATE on the sequence but this failed with an ORA-02205:

SQL> grant update on s1 to u2
  2  /
grant update on s1 to u2
                *
ERROR at line 1:
ORA-02205: only SELECT and ALTER privileges are valid
for sequences
 
Viewing all 330 articles
Browse latest View live