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

ORA-28221

$
0
0
This post shows that if a profile has a password verify function and you assign it to a user who does not have the ALTER USER privilege, that user will not be able to change his or her password without using the REPLACE option. You can see what I mean in the example below, which I tested in Oracle 11.1. First I created a password verify function:

SQL> conn / as sysdba
Connected.
SQL> create or replace function my_verify_function (
  2  username     varchar2,
  3  password     varchar2,
  4  old_password varchar2)
  5  return boolean as
  6  begin
  7  if length(password) < 4 then
  8    raise_application_error
  9    (-20000, 'Password < 4 characters long');
10  else
11    return true;
12  end if;
13  end my_verify_function;
14  /
 
Function created.
 
SQL>

Then I created a profile to use my password verify function:

SQL> create profile for_andrew
  2  limit password_verify_function my_verify_function
  3  /
 
Profile created.
 
SQL>

… and a user to assign the profile to:

SQL> create user andrew
  2  identified by reid1
  3  profile for_andrew
  4  /
 
User created.
 
SQL> grant create session to andrew
  2  /
 
Grant succeeded.
 
SQL>
 
The user logged in and tried to change his password but this failed with an ORA-28221 because the user had not supplied the old password. This happens when you have a password verify function:

SQL> conn andrew/reid1
Connected.
SQL> alter user andrew
  2  identified by reid2
  3  /
alter user andrew
*
ERROR at line 1:
ORA-28221: REPLACE not specified
 
SQL>

The user then used REPLACE to supply the old password and the problem disappeared:

SQL> alter user andrew
  2  identified by reid2
  3  replace reid1
  4  /
 
User altered.
 
SQL>
 
To prove that the password verify function was the cause of the problem, I removed it and the problem went away again:

SQL> conn / as sysdba
Connected.
SQL> alter profile for_andrew
  2  limit password_verify_function null
  3  /
 
Profile altered.
 
SQL> conn andrew/reid2
Connected.
SQL> alter user andrew
  2  identified by reid3
  3  /
 
User altered.
 
SQL>

I reinstated the password verify function:

SQL> conn / as sysdba
Connected.
SQL> alter profile for_andrew
  2  limit password_verify_function my_verify_function
  3  /
 
Profile altered.
 
SQL>
 
Then I granted the ALTER USER privilege to the user and this also solved the problem:
 
SQL> grant alter user to andrew
  2  /
 
Grant succeeded.
 
SQL> conn andrew/reid3
Connected.
SQL> alter user andrew
  2  identified by reid4
  3  /
 
User altered.
 
SQL> conn andrew/reid4
Connected.
SQL>

The ALTER USER privilege allows a user to change other users' passwords so I revoked it: 

SQL> conn / as sysdba
Connected.
SQL> revoke alter user from andrew
  2  /
 
Revoke succeeded.
 
SQL>

The error reappeared, as you might expect:

SQL> conn andrew/reid4
Connected.
SQL> alter user andrew
  2  identified by reid5
  3  /
alter user andrew
*west sussex
ERROR at line 1:
ORA-28221: REPLACE not specified
 
SQL>

One final option is to use the PASSWORD command, which allows a user to change his/her password without any restrictions:

SQL> password
Changing password for ANDREW
Old password:
New password:
Retype new password:
Password changed
SQL> conn andrew/reid5
Connected.
SQL>

ALTER DATABASE BEGIN BACKUP and ALTER DATABASE END BACKUP

$
0
0
I logged into an Oracle 12.1 database, checked it was in ARCHIVELOG mode then ran the ALTER DATABASE BEGIN BACKUP command. This told Oracle I was about to do a hot backup:

C:\Users\Andrew>sqlplus / as sysdba
 
SQL*Plus: Release 12.1.0.1.0 Production on Wed Mar 18 14:45:56 2015
 
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
 
SQL> select log_mode from v$database
  2  /
 
LOG_MODE
------------
ARCHIVELOG
 
SQL> alter database begin backup
  2  /
 
Database altered.
 
SQL>

I copied the database’s datafiles to somewhere safe. I didn’t bother about the control files or the redo log files as I didn’t intend to do anything to them in this example. Clearly, if you try this yourself, you need to work out where the datafiles are beforehand:

C:\app\Administrator\oradata\ORCL1\DATAFILE>copy * Z:\Data\Oracle_Backup
O1_MF_SYSAUX_BDGVW9OT_.DBF
O1_MF_SYSTEM_BDGVZ93W_.DBF
O1_MF_TEMP_BDGW88KG_.TMP
O1_MF_UNDOTBS1_BDGW2MY6_.DBF
O1_MF_USERS_BDGW2LNZ_.DBF
        5 file(s) copied.
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>

I created a MARKER table to prove that the backup and restore had worked as planned:

SQL> create table marker as
  2  select 'Andrew was here' message
  3  from dual
  4  /
 
Table created.
 
SQL>

Then I used the ALTER DATABASE END BACKUP command to tell Oracle the hot backup was finished and closed the database:

SQL> alter database end backup;
 
Database altered.
 
SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL>

I deleted the database’s datafiles:

C:\app\Administrator\oradata\ORCL1\DATAFILE>dir
Volume in drive C has no label.
Volume Serial Number is 269C-9AD9
 
Directory of C:\app\Administrator\oradata\ORCL1\DATAFILE
 
27/01/2015  11:05    <DIR>          .
27/01/2015  11:05    <DIR>          ..
18/03/2015  15:09     3,722,452,992 O1_MF_SYSAUX_BDGVW9OT_.DBF
18/03/2015  15:09       964,698,112 O1_MF_SYSTEM_BDGVZ93W_.DBF
18/03/2015  14:27     1,906,319,360 O1_MF_TEMP_BDGW88KG_.TMP
18/03/2015  15:09     1,378,885,632 O1_MF_UNDOTBS1_BDGW2MY6_.DBF
18/03/2015  15:09     4,650,442,752 O1_MF_USERS_BDGW2LNZ_.DBF
               5 File(s) 12,622,798,848 bytes
               2 Dir(s)   6,003,765,248 bytes free
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>del *.*
C:\app\Administrator\oradata\ORCL1\DATAFILE\*.*, Are you sure (Y/N)? y
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>

Then I restored them from the backup which I made earlier. Again, if you are doing this yourself, you need to work out which files have been lost before you can restore them:

Z:\Data\Oracle_Backup>copy *.* C:\app\Administrator\oradata\ORCL1\DATAFILE
O1_MF_SYSAUX_BDGVW9OT_.DBF
O1_MF_SYSTEM_BDGVZ93W_.DBF
O1_MF_TEMP_BDGW88KG_.TMP
O1_MF_UNDOTBS1_BDGW2MY6_.DBF
O1_MF_USERS_BDGW2LNZ_.DBF
        5 file(s) copied.
 
Z:\Data\Oracle_Backup>

Finally, I mounted the database, recovered it, opened it and confirmed that the MARKER table was still there:

Z:\Data\Oracle_Backup>sqlplus / as sysdba
 
SQL*Plus: Release 12.1.0.1.0 Production on Wed Mar 18 15:50:55 2015
 
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
 
Connected to an idle instance.
 
SQL> startup mount
ORACLE instance started.
 
Total System Global Area 1720328192 bytes
Fixed Size                  2403496 bytes
Variable Size            1023411032 bytes
Database Buffers          687865856 bytes
Redo Buffers                6647808 bytes
Database mounted.
SQL> recover database
Media recovery complete.
SQL> alter database open
  2  /
 
Database altered.
 
SQL> select * from marker
  2  /
 
MESSAGE
---------------
Andrew was here
 
SQL>

Re-Creating Datafiles When Backups Are Unavailable

$
0
0
I found an old copy of the Oracle 9i User-Managed Backup and Recovery Guide and read the following:
 
If a datafile is damaged and no backup of the file is available, then you can still recover the datafile if:
 
·         All archived log files written after the creation of the original datafile are available
·         The control file contains the name of the damaged file (that is, the control file is current, or is a backup taken after the damaged datafile was added to the database)
 
I decided to try this out in an Oracle 12.1 database. First I checked that the database was in ARCHIVELOG mode:

SQL> select log_mode from v$database
  2  /
 
LOG_MODE
------------
ARCHIVELOG
 
SQL>

I created a tablespace called ANDREW:

SQL> create tablespace andrew
  2  datafile 'C:\APP\ADMINISTRATOR\ORADATA\ORCL1\DATAFILE\ANDREW.DBF'
  3  size 20m
  4  /
 
Tablespace created.
 
SQL>

I created a table in the tablespace:

SQL> l
  1  create table marker
  2  tablespace andrew as
  3  select 'Andrew was here again' message
  4* from dual
SQL> /
 
Table created.
 
SQL>

I closed the database:

SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL>

I deleted the tablespace’s datafile:

C:\app\Administrator\oradata\ORCL1\DATAFILE>dir
Volume in drive C has no label.
Volume Serial Number is 269C-9AD9
 
Directory of C:\app\Administrator\oradata\ORCL1\DATAFILE
 
19/03/2015  18:32    <DIR>          .
19/03/2015  18:32    <DIR>          ..
19/03/2015  18:39        20,979,712 ANDREW.DBF
19/03/2015  18:39     3,722,452,992 O1_MF_SYSAUX_BDGVW9OT_.DBF
19/03/2015  18:39       964,698,112 O1_MF_SYSTEM_BDGVZ93W_.DBF
19/03/2015  11:08     1,906,319,360 O1_MF_TEMP_BDGW88KG_.TMP
19/03/2015  18:39     1,378,885,632 O1_MF_UNDOTBS1_BDGW2MY6_.DBF
19/03/2015  18:39     4,650,442,752 O1_MF_USERS_BDGW2LNZ_.DBF
               6 File(s) 12,643,778,560 bytes
               2 Dir(s)   5,940,617,216 bytes free
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>del andrew.dbf
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>dir
Volume in drive C has no label.
Volume Serial Number is 269C-9AD9
 
Directory of C:\app\Administrator\oradata\ORCL1\DATAFILE
 
19/03/2015  18:42    <DIR>          .
19/03/2015  18:42    <DIR>          ..
19/03/2015  18:39     3,722,452,992 O1_MF_SYSAUX_BDGVW9OT_.DBF
19/03/2015  18:39       964,698,112 O1_MF_SYSTEM_BDGVZ93W_.DBF
19/03/2015  11:08     1,906,319,360 O1_MF_TEMP_BDGW88KG_.TMP
19/03/2015  18:39     1,378,885,632 O1_MF_UNDOTBS1_BDGW2MY6_.DBF
19/03/2015  18:39     4,650,442,752 O1_MF_USERS_BDGW2LNZ_.DBF
               5 File(s) 12,622,798,848 bytes
               2 Dir(s)   5,961,596,928 bytes free
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>

I tried to open the database:

C:\app\Administrator\oradata\ORCL1\DATAFILE>sqlplus / as sysdba
 
SQL*Plus: Release 12.1.0.1.0 Production on Thu Mar 19 18:43:02 2015
 
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
 
Connected to an idle instance.
 
SQL> startup
ORACLE instance started.
 
Total System Global Area 1720328192 bytes
Fixed Size                  2403496 bytes
Variable Size            1023411032 bytes
Database Buffers          687865856 bytes
Redo Buffers                6647808 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 2 - see DBWR trace file
ORA-01110: data file 2:
'C:\APP\ADMINISTRATOR\ORADATA\ORCL1\DATAFILE\ANDREW.DBF'
 
SQL>
 
I created the missing datafile:

SQL> alter database create datafile
  2  'C:\APP\ADMINISTRATOR\ORADATA\ORCL1\DATAFILE\ANDREW.DBF'
  3  /
 
Database altered.
 
SQL>

I recovered the datafile:

SQL> recover datafile 'C:\APP\ADMINISTRATOR\ORADATA\ORCL1\DATAFILE\ANDREW.DBF'
Media recovery complete.
SQL>

I looked for the MARKER table but realized that the database was not open:

SQL> select * from marker
  2  /
select * from marker
              *
ERROR at line 1:
ORA-01219: database or pluggable database not open: queries allowed on fixed
tables or views only
 
SQL>
 
I opened the database:

SQL> alter database open
  2  /
 
Database altered.
 
SQL>

… and the MARKER table was there as before:

SQL> select * from marker
  2  /
 
MESSAGE
---------------------
Andrew was here again
 
SQL> select tablespace_name
  2  from dba_tables
  3  where table_name = 'MARKER'
  4  /
 
TABLESPACE_NAME
------------------------------
ANDREW
 
SQL>
 
The Oracle guide went on to say:
 
Note: You cannot re-create any of the datafiles for the SYSTEM tablespace by using the CREATE DATAFILE clause of the ALTER DATABASE statement because the necessary redo data is not available.
 
I will see what happens if you try to do this in a future post.

Rollback to Savepoint Does Not Release Locks

$
0
0
I read that rolling back to a savepoint releases locks. This sounded reasonable so I decided to check it out in an Oracle 11.2 database. I logged in as user John (in blue) and noted my SID for future reference. Then I created a table, inserted a row, committed the change and created a savepoint. Finally I updated the row but did not commit the change, thus setting up a lock:
 
SQL> conn john/smith
Connected.
SQL> select distinct sid from v$mystat
  2  /
 
       SID
----------
       683
 
SQL> create table tab1
  2  (col1 number)
  3  /
 
Table created.
 
SQL> insert into tab1 values(1)
  2  /
 
1 row created.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL> select * from tab1
  2  /
 
      COL1
----------
         1
 
SQL> savepoint sp1
  2  /
 
Savepoint created.
 
SQL> update tab1 set col1 = 2
  2  /
 
1 row updated.
 
SQL> select * from tab1
  2  /
 
      COL1
----------
         2
 
SQL>
 
I logged into a new session as user Fred (in red), noted my SID again and tried to update the same table. This did nothing, as you might expect:
 
SQL> conn fred/bloggs
Connected.
SQL> select distinct sid from v$mystat
  2  /
 
       SID
----------
         5
 
SQL> update john.tab1 set col1 = 3
  2  /
 
I returned to John’s session and checked that I could see the lock in the DBA_WAITERS view. Then I rolled back to the savepoint and checked that the original value had reappeared in the table (it had). However, the lock was still shown in DBA_WAITERS:
 
SQL> show user
USER is "JOHN"
SQL> select holding_session, waiting_session
  2  from dba_waiters
  3  /
 
HOLDING_SESSION WAITING_SESSION
--------------- ---------------
            683               5
 
SQL> rollback to savepoint sp1
  2  /
 
Rollback complete.
 
SQL> select * from tab1
  2  /
 
      COL1
----------
         1
 
SQL> select holding_session, waiting_session
  2  from dba_waiters
  3  /
 
HOLDING_SESSION WAITING_SESSION
--------------- ---------------
            683               5
 
SQL>
 
I guessed that Oracle must still be holding some kind of lock between the two transactions. There was clearly no lock on the data any more as Donald was able to start a new session (in green) and update it with no problems:
 
SQL> conn donald/duck
Connected.
SQL> update john.tab1 set col1 = 4
  2  /
 
1 row updated.
 
SQL> select * from john.tab1
  2  /
 
      COL1
----------
         4
 
SQL> commit
  2  /
 
Commit complete.
 
SQL>
 
User John finished his transaction and the lock disappeared:
 
SQL> show user
USER is "JOHN"
SQL> commit
  2  /
 
Commit complete.
 
SQL> select holding_session, waiting_session
  2  from dba_waiters
  3  /
 
no rows selected
 
SQL>
 
… and this allowed Fred’s earlier update to finish:
 
SQL> conn fred/bloggs
Connected.
SQL> select distinct sid from v$mystat
  2  /
 
       SID
----------
         5
 
SQL> update john.tab1 set col1 = 3
  2  /
 
1 row updated.
 
SQL>

Case Sensitive Passwords in Oracle 11

$
0
0
In version 11, Oracle passwords became case sensitive. You can see what I mean in the example below:

SQL> conn / as sysdba
Connected.
SQL> alter user system identified by manager
  2  /
 
User altered.
 
SQL> conn system/manager
Connected.
SQL> conn system/MANAGER
ERROR:
ORA-01017: invalid username/password; logon denied
 
Warning: You are no longer connected to ORACLE.
SQL>
 
The DBA_USERS view no longer contains the encrypted password, except when the user is identified externally:
 
SQL> conn / as sysdba
Connected.
SQL> alter user system identified externally
  2  /
 
User altered.
 
SQL> select password from dba_users
  2  where username = 'SYSTEM'
  3  /
 
PASSWORD
------------------------------
EXTERNAL
 
SQL> alter user system identified by manager
  2  /
 
User altered.
 
SQL> select password from dba_users
  2  where username = 'SYSTEM'
  3  /
 
PASSWORD
------------------------------
 
SQL>
 
You can see the Oracle 10 encrypted password in the NAME column of SYS.USER$ and the Oracle 11 encrypted value of the password in the SPARE4 column of the same table:
 
SQL> select password from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
PASSWORD
------------------------------
D4DF7931AB130E37
 
SQL> select spare4 from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
SPARE4
-----------------------------------------------------------------
S:9FA0ADFDC164534A13A388167C4D75BC6C9CF35F7A9CC58F1CDBB1DC7653
 
SQL>
 
If you use the Oracle 10 encrypted value to reset the password, the Oracle 11 encrypted value disappears from the SPARE4 column:
 
SQL> alter user system identified by values 'D4DF7931AB130E37'
  2  /
 
User altered.
 
SQL> select password from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
PASSWORD
------------------------------
D4DF7931AB130E37
 
SQL> select spare4 from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
SPARE4
-----------------------------------------------------------------
 
SQL>
 
… and the password is no longer case sensitive:
 
SQL> conn system/manager
Connected.
SQL> conn system/MANAGER
Connected.
SQL>
 
Conversely, if you use the Oracle 11 encrypted value to reset the password, the Oracle 10 encrypted value disappears from the PASSWORD column:
 
SQL> alter user system identified by values
  2  'S:FA743A680B015952982BB2B501B7BC623F1AA11093AC95E58D67B18A2AC2'
  3  /
 
User altered.
 
SQL> select password from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
PASSWORD
------------------------------
 
SQL> select spare4 from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
SPARE4
-----------------------------------------------------------------
S:FA743A680B015952982BB2B501B7BC623F1AA11093AC95E58D67B18A2AC2
 
SQL>
 
… and the password becomes case sensitive again:
 
SQL> conn system/manager
Connected.
SQL> conn system/MANAGER
ERROR:
ORA-01017: invalid username/password; logon denied
 
Warning: You are no longer connected to ORACLE.
SQL>

A Simple Example With V$BACKUP

$
0
0
I tested this in an Oracle 12.1 database. The V$BACKUP view tells you if a datafile is in hot backup mode. I started off with none of the datafiles in hot backup mode so they were all shown as NOT ACTIVE:

SQL> select file#, status from v$backup
  2  /
 
     FILE# STATUS
---------- ------------------
         1 NOT ACTIVE
         2 NOT ACTIVE
         3 NOT ACTIVE
         5 NOT ACTIVE
         6 NOT ACTIVE
 
SQL>

I put the USERS tablespace into hot backup mode and its datafile changed to ACTIVE in V$BACKUP until I took the tablespace out of hot backup mode:

SQL> alter tablespace users begin backup
  2  /
 
Tablespace altered.
 
SQL> select file_id from dba_data_files
  2  where tablespace_name = 'USERS'
  3  /
 
   FILE_ID
----------
         6
 
SQL> select file#, status from v$backup
  2  /
 
     FILE# STATUS
---------- ------------------
         1 NOT ACTIVE
         2 NOT ACTIVE
         3 NOT ACTIVE
         5 NOT ACTIVE
         6 ACTIVE
 
SQL> alter tablespace users end backup
  2  /
 
Tablespace altered.
 
SQL> select file#, status from v$backup
  2  /
 
     FILE# STATUS
---------- ------------------
         1 NOT ACTIVE
         2 NOT ACTIVE
         3 NOT ACTIVE
         5 NOT ACTIVE
         6 NOT ACTIVE
 
SQL>

… and when I put the whole database into hot backup mode, all the datafiles were shown as ACTIVE:

SQL> alter database begin backup
  2  /
 
Database altered.
 
SQL> select file#, status from v$backup
  2  /
 
     FILE# STATUS
---------- ------------------
         1 ACTIVE
         2 ACTIVE
         3 ACTIVE
         5 ACTIVE
         6 ACTIVE
 
SQL> alter database end backup
  2  /
 
Database altered.
 
SQL> select file#, status from v$backup
  2  /
 
     FILE# STATUS
---------- ------------------
         1 NOT ACTIVE
         2 NOT ACTIVE
         3 NOT ACTIVE
         5 NOT ACTIVE
         6 NOT ACTIVE
 
SQL>

RECOVER DATABASE TEST

$
0
0
I logged into an Oracle 12.1 database and ran the ALTER DATABASE BEGIN BACKUP command. This told Oracle I was about to start a hot backup:

C:\Users\Administrator>sqlplus / as sysdba
 
SQL*Plus: Release 12.1.0.1.0 Production on Thu Mar 26 10:08:51 2015
 
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
 
SQL> alter database begin backup
  2  /
 
Database altered.
 
SQL>

I copied one of the database’s datafiles somewhere safe:

C:\app\Administrator\oradata\ORCL1\DATAFILE>copy O1_MF_USERS_BDGW2LNZ_.DBF z:\data\oracle_backup
        1 file(s) copied.
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>

Then I used the ALTER DATABASE END BACKUP command to tell Oracle the hot backup was finished and closed the database:

SQL> alter database end backup;
 
Database altered.
 
SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL>

I deleted the datafile I had backed up:

C:\app\Administrator\oradata\ORCL1\DATAFILE>del O1_MF_USERS_BDGW2LNZ_.DBF
 
C:\app\Administrator\oradata\ORCL1\DATAFILE>

Then I restored it from the backup which I had made earlier:

Z:\Data\Oracle_Backup>copy O1_MF_USERS_BDGW2LNZ_.DBF C:\app\Administrator\oradata\ORCL1\DATAFILE
        1 file(s) copied.
 
Z:\Data\Oracle_Backup>

I mounted the database:

Z:\Data\Oracle_Backup>sqlplus / as sysdba
 
SQL*Plus: Release 12.1.0.1.0 Production on Wed Mar 18 15:50:55 2015
 
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
 
Connected to an idle instance.
 
SQL> startup mount
ORACLE instance started.
 
Total System Global Area 1720328192 bytes
Fixed Size                  2403496 bytes
Variable Size            1023411032 bytes
Database Buffers          687865856 bytes
Redo Buffers                6647808 bytes
Database mounted.
SQL>

I read in some Oracle documentation that if you added the word TEST after a RECOVER command, you could test the recovery you were about to attempt. I decided to try it out but the messages it produced did not seem to tell me whether the recovery would succeed or fail:

SQL> recover database test
ORA-10574: Test recovery did not corrupt any data block
ORA-10573: Test recovery tested redo from change 11524259 to 11525796
ORA-10572: Test recovery canceled due to errors
ORA-10585: Test recovery can not apply redo that may modify control file
 
SQL>

I decided to give it a try anyway and it worked without problem:

SQL> recover database
Media recovery complete.
SQL> alter database open
  2  /
 
Database altered.
 
SQL>

Recursion in Oracle 12

$
0
0
Oracle 12 has a new parameter called PGA_AGGREGATE_LIMIT:

SQL> conn system/manager
Connected.
SQL> l
  1  select value from v$parameter
  2* where name = 'pga_aggregate_limit'
SQL> /
 
VALUE
--------------------
2147483648
 
SQL>

You cannot set it below 2 gigabytes:

SQL> alter system
  2  set pga_aggregate_limit = 1g;
alter system
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because
specified value is invalid
ORA-00093: pga_aggregate_limit must be between 2048M
and 100000G
 
SQL> 

In earlier versions of Oracle, if you let recursive code get out of control, it could use up all the memory on the underlying server. I decided to try this out on Oracle 12:

SQL> create or replace procedure recursion is
  2  begin
  3  recursion();
  4  end;
  5  /
 
Procedure created.
 
SQL> exec recursion();

While this was running, I found I could still use the machine so I took a look in the alert log and saw the following errors at the end:

Thu Feb 12 17:43:34 2015
Errors in file C:\APP\ADMINISTRATOR\diag\rdbms\orcl1\orcl1\trace\orcl1_ora_2796.trc  (incident=19267):
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT
Incident details in: C:\APP\ADMINISTRATOR\diag\rdbms\orcl1\orcl1\incident\incdir_19267\orcl1_ora_2796_i19267.trc
Errors in file C:\APP\ADMINISTRATOR\diag\rdbms\orcl1\orcl1\trace\orcl1_ora_2796.trc  (incident=19268):
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT
Incident details in: C:\APP\ADMINISTRATOR\diag\rdbms\orcl1\orcl1\incident\incdir_19268\orcl1_ora_2796_i19268.trc

When I looked in V$SESSION_EVENT, I saw that there had been a brief wait on the acknowledge over PGA limit event:

SQL> l
  1  select event, time_waited/100
  2  from v$session_event
  3* where sid = 11
SQL> /
 
EVENT                          TIME_WAITED/100
------------------------------ ---------------
acknowledge over PGA limit                7.05
Disk file operations I/O                     0
log buffer space                             0
SQL*Net message to client                    0
SQL*Net message from client             116.29
SQL*Net break/reset to client                0
 
6 rows selected.
 
SQL>

After this, the session was killed:
 
SQL> select status from v$session where sid = 11;
 
STATUS
--------
KILLED
 
SQL>

… and there was a message to this effect in the alert log:

Thu Feb 12 17:52:59 2015
Errors in file C:\APP\ADMINISTRATOR\diag\rdbms\orcl1\orcl1\incident\incdir_19267\orcl1_ora_2796_i19267.trc:
ORA-00028: your session has been killed
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT

The only problem I could see was that no error message was returned to the session running the recursion.

As an extra test, I used SYS to run the recursive procedure:

C:\Users\Administrator>sqlplus / as sysdba
 
SQL*Plus: Release 12.1.0.1.0 Production on Fri Feb 13 09:02:36 2015
 
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
 
SQL> exec system.recursion();

This wrote more serious messages to the alert log:

Fri Feb 13 09:04:39 2015
PGA_AGGREGATE_LIMIT has been exceeded but some processes using the most PGA
memory are not eligible to receive ORA-4036 interrupts.  Further occurrences
of this condition will be written to the trace file of the CKPT process.

The session remained ACTIVE and V$SESSION_EVENT did not know what it was waiting for:

SQL> select sid from v$session
  2  where username = 'SYS';
 
       SID
----------
       237
 
SQL> select status from v$session
  2  where sid = 237;
 
STATUS
--------
ACTIVE
 
SQL> select event, time_waited/100
  2  from v$session_event
  3  where sid = 237
  4  /
 
EVENT                                    TIME_WAITED/100
---------------------------------------- ---------------
Disk file operations I/O                               0
db file sequential read                              .09
SQL*Net message to client                              0
SQL*Net message from client                       101.92
 
SQL>

One Cause of ORA-01092

$
0
0
I saw the following error in a job which had just recreated the control file of a test database after cloning:

SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   3
2   33   34   35   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56   57   58   59   60   61   62   63
  64   65   66   67   68   69   70   71   72   73   74   75   76   77   78   79   80   81   82   83   84   85   86   87   88   89   90   91   92   93   94
95   96   97   98   99  100  101  102  103  104  105  106  107  108  109  110  111  112  113  114  115  116  117  118  119  120  121  122  123  124  125  126
  127  128  129  130  131  132  133  134  135  136  137
Control file created.
 
SQL> ALTER DATABASE OPEN RESETLOGS
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
 
SQL>

I looked in the alert log and noticed the errors below:

Wed Apr  1 19:30:46 2015
Errors in file /oracle/app/oracle/product/10.2.0/admin/mrmdpt1/udump/mrmdpt1_ora_8712.trc:
ORA-00600: internal error code, arguments: [25025], [115], [], [], [], [], [], []
Wed Apr  1 19:30:47 2015
Errors in file /oracle/app/oracle/product/10.2.0/admin/mrmdpt1/udump/mrmdpt1_ora_8712.trc:
ORA-00600: internal error code, arguments: [25025], [115], [], [], [], [], [], []
Wed Apr  1 19:30:47 2015
Error 600 happened during db open, shutting down database
USER: terminating instance due to error 600
Instance terminated by USER, pid = 8712
ORA-1092 signalled during: ALTER DATABASE OPEN RESETLOGS...

I checked the SQL which had recreated the control file. I saw that one of the datafiles from the source database was missing. The missing file was called '/agasprd/mrmprod/mrm_tables3/undo_1a.dbf'. I checked its file_id in the source database:

SQL> l
  1  select file_id from dba_data_files
  2  where file_name =
  3* '/agasprd/mrmprod/mrm_tables3/undo_1a.dbf'
SQL> /
 
   FILE_ID
----------
       115
 
SQL>

I noticed that it matched the 2nd parameter after the ORA-00600 (i.e. [115]). If this happens to you, you should correct the SQL so that it includes all the source database’s datafiles then repeat the cloning process from the start.

SUCCESS and FAILURE Columns in DBA_STMT_AUDIT_OPTS

$
0
0
I tested this in Oracle 10.2. DBA_STMT_AUDIT_OPTS records auditing options which are currently in effect. If no auditing has been requested, it will be empty:
 
SQL> select user_name, audit_option, success, failure
  2  from dba_stmt_audit_opts
  3  /
 
no rows selected
 
SQL>
 
You can audit successful connections as follows:
 
SQL> audit create session by system whenever successful
  2  /
 
Audit succeeded.
 
SQL>
 
This will then be recorded in DBA_STMT_AUDIT_OPTS. The SUCCESS column will be set to BY ACCESS to show that only successful connections are being audited:   
 
SQL> select user_name, audit_option, success, failure
  2  from dba_stmt_audit_opts
  3  /
 
USER_NAME  AUDIT_OPTION    SUCCESS    FAILURE
---------- --------------- ---------- ----------
SYSTEM     CREATE SESSION  BY ACCESS  NOT SET
 
SQL>
 
You can stop the auditing like this:
 
SQL> noaudit create session by system whenever successful
  2  /
 
Noaudit succeeded.
 
SQL>
 
…and the entry will disappear from DBA_STMT_AUDIT_OPTS:
 
SQL> select user_name, audit_option, success, failure
  2  from dba_stmt_audit_opts
  3  /
 
no rows selected
 
SQL>
 
Here is how you audit unsuccessful connections. Note that in the context of the AUDIT and NOAUDIT commands, CREATE SESSION and CONNECT have the same meaning:
 
SQL> audit connect by system whenever not successful
  2  /
 
Audit succeeded.
 
SQL>
 
This will also be recorded in DBA_STMT_AUDIT_OPTS but the FAILURE column will be set to BY ACCESS to show that only failed connections are being audited:   
 
 
SQL> select user_name, audit_option, success, failure
  2  from dba_stmt_audit_opts
  3  /
 
USER_NAME  AUDIT_OPTION    SUCCESS    FAILURE
---------- --------------- ---------- ----------
SYSTEM     CREATE SESSION  NOT SET    BY ACCESS
 
SQL>
 
As before, stopping the auditing removes the entry from DBA_STMT_AUDIT_OPTS:
 
SQL> noaudit connect by system whenever not successful
  2  /
 
Noaudit succeeded.
 
SQL> select user_name, audit_option, success, failure
  2  from dba_stmt_audit_opts
  3  /
 
no rows selected
 
SQL>

A Difference Between SQL*Plus and SQL Developer

$
0
0
A third-party supplier delivered some SQL today but it did not work in SQL*Plus. We asked the supplier about this and it turned that the code had been tested in SQL Developer. The reason for the failure was as follows. If you end a line of SQL with a semi-colon then add a comment afterwards, SQL*Plus rejects it with an ORA-00911

SQL> @test1
SQL> set echo on
SQL> select 'Comment->' from dual; /*Andrew was here*/
  2  select 'More SQL' from dual;
select 'Comment->' from dual; /*Andrew was here*/
                            *
ERROR at line 1:
ORA-00911: invalid character
 
SQL>

To get the code to work, you need to include the comment before the semi-colon:

SQL> @test2
SQL> set echo on
SQL> select 'Comment->' from dual /*Andrew was here*/;
 
'COMMENT-
---------
Comment->
 
SQL> select 'More SQL' from dual;
 
'MORESQL
--------
More SQL
 
SQL>

However, if you try this in SQL Developer, both options work (as usual, click on the images to enlarge them and bring them into focus):

 
 

ORA-01114 Not Recorded Correctly in Alert Log

$
0
0
A user reported an ORA-01114 and an ORA-27069 in a 3rd party application running against an Oracle 11.1 database:

ERROR 28/01/2015 10:32:37  INF2 LKPDP_10:READER_1_1  RR_4035    SQL Error [
ORA-01114: IO error writing block to file 201 (block # 524367)
ORA-27069: attempt to do I/O beyond the range of the file
Additional information: 524367
Additional information: 7
Additional information: 524289
ORA-01114: IO error writing block to file 201 (block # 524367)
ORA-27069: attempt to do I/O beyond the range of the file
Additional information: 524367
Additional information: 7
Additional information: 524289

I searched the database’s alert log but could not find either of the errors. I asked the user when this had happened and looked at the corresponding place in the alert log. Then I noticed that the ORA-01114 had been recorded without the leading zero:

Wed Jan 28 10:32:51 2015
ORA-1114 : opiodr aborting process unknown ospid (23531_1)
 
… but there was still no sign of the ORA-27069.

ORA-00600: internal error code, arguments: [kzdlk_zt2 err]

$
0
0
This example is based on an error which a colleague showed me recently. I logged into an Oracle 11.1 database, reset its SYSTEM password and checked the encrypted value: 

Oracle11 > sqlplus / as sysdba
 
SQL*Plus: Release 11.1.0.6.0 - Production on Wed Feb 4 18:10:38 2015
 
Copyright (c) 1982, 2007, Oracle.  All rights reserved.
 
Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
 
SQL> select name from v$database
  2  /
 
NAME
---------
PQEDPT1
 
SQL> alter user system
  2  identified by manager
  3  /
 
User altered.
 
SQL> select password from sys.user$
  2  where name = 'SYSTEM'
  3  /
 
PASSWORD
------------------------------
D4DF7931AB130E37
 
SQL>

I then logged into an Oracle 11.2 database, created a link to the database above, tried to use it and saw an error:

Oracle11 > sqlplus system/manager
 
SQL*Plus: Release 11.2.0.1.0 Production on Wed Feb 4 18:13:39 2015
 
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
 
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
 
SQL> select name from v$database
  2  /
 
NAME
---------
BUSDPT1
 
SQL> create database link andrew
  2  connect to system
  3  identified by values 'D4DF7931AB130E37'
  4  using 'PQEDPT1'
  5  /
 
Database link created.
 
SQL> select * from dual@andrew
  2  /
select * from dual@andrew
                   *
ERROR at line 1:
ORA-00600: internal error code, arguments: [kzdlk_zt2 err],
[18446744073709551603], [], [], [], [], [], [], [], [], [], []
 
SQL>

I did some research and it seems that the identified by values syntax above is an undocumented feature. I altered the database link, supplying the unencrypted value, and it worked:

SQL> alter database link andrew
  2  connect to system
  3  identified by manager
  4  /
alter database link andrew
                    *
ERROR at line 1:
ORA-01031: insufficient privileges
 
SQL> grant alter database link to system
  2  /
 
Grant succeeded.
 
SQL> alter database link andrew
  2  connect to system
  3  identified by manager
  4  /
 
Database link altered.
 
SQL> select * from dual@andrew
  2  /
 
D
-
X
 
SQL>

So, if you are creating a new database link, you need to do it like this:

SQL> drop database link andrew
  2  /
 
Database link dropped.
 
SQL> create database link andrew
  2  connect to system
  3  identified by manager
  4  using 'PQEDPT1'
  5  /
 
Database link created.
 
SQL> select * from dual@andrew
  2  /
 
D
-
X

enq: TM - contention

$
0
0
This example was tested in an Oracle 11.1 database. I created a DEPT (or parent) table, added a couple of departments then made it available to other database users:

SQL> conn andrew/reid
Connected.
SQL> create table dept
  2  (dept_code varchar2(2),
  3   dept_desc varchar2(10))
  4  /
 
Table created.
 
SQL> insert into dept
  2  (dept_code, dept_desc)
  3  values
  4  ('10','IT')
  5  /
 
1 row created.
 
SQL> insert into dept
  2  (dept_code, dept_desc)
  3  values
  4  ('20','Sales')
  5  /
 
1 row created.
 
SQL> select * from dept
  2  /
 
DEPT_CODE  DEPT_DESC
---------- ----------
10         IT
20         Sales
 
SQL> grant all on dept to public
  2  /
 
Grant succeeded.
 
SQL>

I created an EMP (or child) table and tried to cross-check the EMP_DEPT column against the DEPT_CODE column in the DEPT table. This failed with an ORA-02270 as DEPT_CODE in the DEPT table was not unique. This was quite understandable because, if I had joined the EMP and DEPT tables to get the description (DEPT_DESC) for each employee’s department, I needed to be sure that only one value would be returned. I have covered this before but decided it would do no harm to repeat it here. I made the DEPT_CODE column unique in the DEPT table and the problem went away. I added two names to the EMP table with misspelt names (you will see why later). Then I made the table available to other database users:

SQL> create table emp
  2  (emp_name varchar2(10),
  3   emp_dept varchar2(2),
  4   constraint fk1
  5   foreign key(emp_dept)
  6   references dept(dept_code))
  7  /
references dept(dept_code))
                 *
ERROR at line 6:
ORA-02270: no matching unique or primary key for this
column-list
 
SQL> alter table dept
  2  add constraint dept_no_pk
  3  unique(dept_code)
  4  /
 
Table altered.
 
SQL> create table emp
  2  (emp_name varchar2(10),
  3   emp_dept varchar2(2),
  4   constraint fk1
  5   foreign key(emp_dept)
  6   references dept(dept_code))
  7  /
 
Table created.
 
SQL> insert into andrew.emp
  2  (emp_name, emp_dept)
  3  values
  4  ('Dayvid', '10')
  5  /
 
1 row created.
 
SQL> insert into andrew.emp
  2  (emp_name, emp_dept)
  3  values
  4  ('Edwood', '10')
  5  /
 
1 row created.
 
SQL> grant all on emp to public
  2  /
 
Grant succeeded.
 
SQL> 

USERA logged into the database, noticed one of the spelling mistakes, corrected it but did not commit the change:

SQL> conn usera/usera
Connected.
SQL> select * from andrew.emp
  2  /
 
EMP_NAME   EMP_DEPT
---------- ----------
Dayvid     10
Edwood     10
 
SQL> update andrew.emp
  2  set emp_name = 'David'
  3  where emp_name = 'Dayvid'
  4  /
 
1 row updated.
 
SQL> 

USERB logged into the database and tried to change the DEPT_CODE for Sales from 20 to 30 but nothing appeared to happen:

SQL> conn userb/userb
Connected.
SQL> update andrew.dept
  2  set dept_code = '30'
  3  where dept_desc = 'Sales'
  4  / 

USERB reported the problem to a DBA who investigated it as follows:

SQL> conn / as sysdba
Connected.
SQL> select event, state from v$session
  2  where username = 'USERB'
  3  /
 
EVENT                          STATE
------------------------------ -------------------
enq: TM - contention           WAITING
 
SQL>

This showed her that the problem was caused by a foreign key locking issue so she looked at the locks in Enterprise Manager:

 
This showed that the child table was EMP.
 
Eventually, USERA committed his change:

SQL> conn usera/usera
Connected.
SQL> select * from andrew.emp
  2  /
 
EMP_NAME   EMP_DEPT
---------- ----------
Dayvid     10
Edwood     10
 
SQL> update andrew.emp
  2  set emp_name = 'David'
  3  where emp_name = 'Dayvid'
  4  /
 
1 row updated.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL>

And USERB’s transaction finished moments later so he was able to commit it too:

SQL> conn userb/userb
Connected.
SQL> update andrew.dept
  2  set dept_code = '30'
  3  where dept_desc = 'Sales'
  4  /
 
1 row updated.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL>

The DBA looked to see how the EMP (child) table had been created. (I won’t go into how she knew Andrew’s password):

SQL> conn andrew/reid
Connected.
SQL> select dbms_metadata.get_ddl('TABLE','EMP')
  2  from dual
  3  /
 
DBMS_METADATA.GET_DDL('TABLE','EMP')
--------------------------------------------------------------------------------
 
  CREATE TABLE "ANDREW"."EMP"
   (    "EMP_NAME" VARCHAR2(10),
        "EMP_DEPT" VARCHAR2(2),
         CONSTRAINT "FK1" FOREIGN KEY ("EMP_DEPT")
          REFERENCES "ANDREW"."DEPT" ("DEPT_CODE") ENABLE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "USERS"
 
SQL> 

She noticed that the EMP_DEPT column was used for referential integrity checking against the DEPT table. For this to work efficiently, there needs to be an index on this column but Oracle does not enforce this requirement. The DBA looked for indexes on the EMP table but did not find any:

SQL> l
  1  select index_name, column_name, column_position
  2  from dba_ind_columns
  3  where table_owner = 'ANDREW'
  4  and table_name = 'EMP'
  5* order by 1,3
SQL> /
 
no rows selected
 
SQL>

She created the appropriate index:

SQL> l
  1  create index andrew.emp_ind1
  2* on andrew.emp(emp_dept)
SQL> /
 
Index created.
 
SQL> 

USERA noticed the other spelling mistake, corrected it but did not commit the change:

SQL> conn usera/usera
Connected.
SQL> select * from andrew.emp
  2  /
 
EMP_NAME   EMP_DEPT
---------- ----------
David      10
Edwood     10
 
SQL> update andrew.emp
  2  set emp_name = 'Edward'
  3  where emp_name = 'Edwood'
  4  /
 
1 row updated.
 
SQL> 

USERB decided to change the DEPT_CODE for the Sales department to 40 and this time, the update worked immediately:

SQL> conn userb/userb
Connected.
SQL> update andrew.dept
  2  set dept_code = '40'
  3  where dept_desc = 'Sales'
  4  /
 
1 row updated.
 
SQL>

statement suspended, wait error to be cleared

$
0
0
This happened in an Oracle 11.2.0.4 database. A colleague complained of poor performance. I looked to see what his session was waiting for:

SQL> l
  1  select event
  2  from v$session_wait
  3  where sid = 226
  4* and state = 'WAITING'
SQL> /
 
EVENT
----------------------------------------------------------------
statement suspended, wait error to be cleared
 
SQL>

I looked in the alert log and saw the following error:

statement in resumable session 'User WORK(105), Session 226, Instance 1' was suspended due to
    ORA-01653: unable to extend table WORK.WRK_CONSUMPTION_NHH by 8192 in tablespace MI_DATA

I increased the size of one of the tablespace’s datafiles:

SQL> l
  1  alter database datafile
  2  '/cogdbase/ecocog5/eco_data/mi_data2.dbf'
  3* resize 31g
SQL> /
 
Database altered.
 
SQL>

Then I looked in the alert log and saw that the statement had started working again:

Mon Apr 13 16:23:19 2015
Completed: alter database datafile
'/cogdbase/ecocog5/eco_data/mi_data2.dbf'
resize 31g
Mon Apr 13 16:23:19 2015
statement in resumable session 'User WORK(105), Session 226, Instance 1' was resumed

Finally, I checked the session and it was waiting for a different event:

SQL> l
  1  select event
  2  from v$session_wait
  3  where sid = 226
  4* and state = 'WAITING'
SQL> /
 
EVENT
----------------------------------------------------------------
db file sequential read
 
SQL>

FULL and NO_INDEX Hints

$
0
0
I was reading about hints and decided to try out a couple on an Oracle 11.2 database. First I created a table, added some data and created an index:

SQL> create table t1 (c1 varchar2(30))
  2  /
 
Table created.
 
SQL> insert into t1 select table_name from dba_tables
  2  /
 
3159 rows created.
 
SQL> create index i1 on t1(c1)
  2  /
 
Index created.
 
SQL>

I ran a SELECT statement on the table. I thought it would use the index and it did:

SQL> set autotrace on explain
SQL> select count(*)
  2  from t1
  3  where c1 = 'T1'
  4  /
 
  COUNT(*)
----------
         1
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2349582935
 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    17 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |      |     1 |    17 |            |          |
|*  2 |   INDEX RANGE SCAN| I1   |     1 |    17 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("C1"='T1')
 
Note
-----
   - dynamic sampling used for this statement (level=2)
 
SQL>

I then added a full hint to force the optimizer to choose a full table scan and this worked too:
 
SQL> select /*+ full(t1) */ count(*)
  2  from t1
  3  where c1 = 'T1'
  4  /
 
  COUNT(*)
----------
         1
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3693069535
 
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    17 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |    17 |            |          |
|*  2 |   TABLE ACCESS FULL| T1   |     1 |    17 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter("C1"='T1')
 
Note
-----
   - dynamic sampling used for this statement (level=2)
 
SQL>

I added an alias after the table name. The hint stopped working and the query used the index again:

SQL> select /*+ full(t1) */ count(*)
  2  from t1 my_alias
  3  where c1 = 'T1'
  4  /
 
  COUNT(*)
----------
         1
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2349582935
 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    17 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |      |     1 |    17 |            |          |
|*  2 |   INDEX RANGE SCAN| I1   |     1 |    17 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("C1"='T1')
 
Note
-----
   - dynamic sampling used for this statement (level=2)
 
SQL>

That was because, if you use an alias, the hint must specify the alias, not the table name. I changed the hint to do this and the optimizer chose a full table scan again:

SQL> select /*+ full(my_alias) */ count(*)
  2  from t1 my_alias
  3  where c1 = 'T1'
  4  /
 
  COUNT(*)
----------
         1
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3693069535
 
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    17 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |    17 |            |          |
|*  2 |   TABLE ACCESS FULL| T1   |     1 |    17 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter("C1"='T1')
 
Note
-----
   - dynamic sampling used for this statement (level=2)
 
SQL>

It occurred to me that I might also be able to force a full table scan by telling Oracle not to use a particular index. I did this with a no_index hint and it worked as expected:

SQL> select /*+ no_index(t1 i1) */ count(*)
  2  from t1
  3  where c1 = 'T1'
  4  /
 
  COUNT(*)
----------
         1
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3693069535
 
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    17 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |    17 |            |          |
|*  2 |   TABLE ACCESS FULL| T1   |     1 |    17 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter("C1"='T1')
 
Note
-----
   - dynamic sampling used for this statement (level=2)
 
SQL>

COMMIT Causes ORA-03113

$
0
0
A colleague had a problem with an Oracle 11.2.0.1 database today. It affected the following table:

SQL> desc bepe.sd_national_holiday
Name                       Null?    Type
-------------------------- -------- ------------------
SD_NATIONAL_HOLIDAY_ID     NOT NULL NUMBER(15)
DAY_DATE                            DATE
DESCRIPTION                         VARCHAR2(500)
CREATED_BY                 NOT NULL VARCHAR2(100)
CREATION_DATE              NOT NULL TIMESTAMP(6)
ACTIVITY_BY                NOT NULL VARCHAR2(100)
ACTIVITY_DATE              NOT NULL TIMESTAMP(6)
TCN                        NOT NULL NUMBER
 
SQL>

The table was empty:

SQL> select count(*) from bepe.sd_national_holiday
  2  /
 
  COUNT(*)
----------
         0
 
SQL>

… but, when I tried to add data to it, the COMMIT, which followed, failed with an ORA-03113. Typing EXIT, without doing a COMMIT, caused the same problem:

SQL> insert into bepe.sd_national_holiday
  2  (day_date) values ('15-APR-2015')
  3  /
 
1 row created.
 
SQL> commit
  2  /
commit
     *
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 7037
Session ID: 133 Serial number: 6339
 
SQL> conn /
Connected.
SQL> insert into bepe.sd_national_holiday
  2  (day_date) values ('15-APR-2015')
  3  /
 
1 row created.
 
SQL> exit
ERROR:
ORA-03113: end-of-file on communication channel
Process ID: 0
Session ID: 133 Serial number: 6343
 
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options (with complications)
APXDEV1 /export/home/oracle/andrew >

The table remained empty:

SQL> l
  1  select count(*)
  2* from bepe.sd_national_holiday
SQL> /
 
  COUNT(*)
----------
         0
 
SQL>

… and trying to move it did not work either:

SQL> l
  1  alter table bepe.sd_national_holiday
  2* move tablespace apex_13482906934262524
SQL> /
alter table bepe.sd_national_holiday
                 *
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 11685
Session ID: 156 Serial number: 21804
 
SQL>

I was able to reproduce this error again and again. I thought there might be some corruption in the underlying data file but dbverify did not show anything. I looked at the messages in the alert log:

ORA-07445: exception encountered: core dump [qesrcRseObj_Invalidate()+4] [SIGSEGV] [ADDR:0x18] [PC:0x1029AFAC4] [Address not mapped to object] []

The closest match I could find for these on My Oracle Support was unpublished bug 9025861. In Oracle 11.2, results from functions run against tables can be cached. Then Oracle can access these cached values rather than rerun the functions. The suggested fix for this bug is to upgrade to Oracle 11.2.0.2 or set result_cache_max_size to zero, which stops cached results being used. I set the parameter to zero:

SQL> l
  1  select value from v$parameter
  2* where name = 'result_cache_max_size'
SQL> /
 
VALUE
----------
2621440
 
SQL> alter system set result_cache_max_size = 0
  2  /
 
System altered.
 
SQL>

… and the problem went away:

SQL> insert into bepe.sd_national_holiday
  2  (day_date) values ('15-APR-2015')
  3  /
 
1 row created.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL>

Strangely enough, resetting the parameter to its previous value did not make the problem return:

SQL> alter system set result_cache_max_size = 2621440
  2  /
 
System altered.
 
SQL> select value from v$parameter
  2  where name = 'result_cache_max_size'
  3  /
 
VALUE
----------
2621440
 
SQL> insert into bepe.sd_national_holiday
  2  (day_date) values ('16-APR-2015')
  3  /
 
1 row created.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL> 

However, this is not a permanent cure. I did the same thing just over a month ago and the problem went away then too but, as you can see, it returned today for no apparent reason.

We noticed that an Oracle 11.2.0.2 database, which is being used for similar work, has not been affected by this problem so upgrading to this version might be the safest option.

Default Size of a CHAR Column

$
0
0
If you do not specify a size for a CHAR column, the default is 1. You can see what I mean in the example below, which I tested on Oracle 11.2:

SQL> create table t1
  2  (c1 char,
  3   c2 char(1))
  4  /
 
Table created.
 
SQL> desc t1
Name                       Null?    Type
-------------------------- -------- ------------------
C1                                  CHAR(1)
C2                                  CHAR(1)
 
SQL> 

However, if you rely on defaults like this and the software supplier changes them, you could be left with an application which does not work. 

ORA-00604 and ORA-00001

$
0
0
This happened in an Oracle 11.1.0.6.0 database:
 
A developer reported problems when running a CREATE OR REPLACE TYPE statement in a development database. It was failing with an ORA-00604 followed by an ORA-00001. These messages could be seen again and again in the alert log:

ORA-00604: error occurred at recursive SQL level 3
ORA-00001: unique constraint (SYS.I_OBJ1) violated

I could see no reason for this so I did some research on the Internet then suggested that the data dictionary might be corrupted. This was quite possible as a number of people have the SYSTEM password for the database in question so somebody could easily have done something silly with it.
 
A second colleague reported the same errors when compiling packages and dropping and creating global temporary tables. Another DBA looked at the problem this time. He tried to recompile all invalid objects in the database and noticed that the compilation of one procedure displayed several errors before failing with a core dump. He amended the procedure a bit at a time to fix the errors until the compilation no longer caused a core dump. He then purged the recycle bin and asked the 2nd developer to try again. He reported that the problem had gone away.
 
I reran the CREATE OR REPLACE TYPE statement provided by the 1st developer and it worked too.  

Overloading

$
0
0
I was looking at a 3rd party application running in an Oracle 11.2 database. I listed the source code of one of the packages and noticed that it contained 5 versions of the same procedure. I have never done any Oracle development so I am not a PL/SQL expert and this seemed strange to me at first. Then I thought about what I have been learning about Java recently and realized that this was Oracle doing overloading. This allows more than one procedure to have a given name as long as each version has a different set of parameters. Oracle then chooses the appropriate version based on the parameters supplied. You can see what I mean in the example below. A package is created called PACKAGE1. It contains two versions of a procedure called PROCEDURE1. Each version displays the parameters supplied to it. So, if you supply 1 parameter, Oracle chooses to run the version which accepts (and displays) 1 parameter. Conversely, if you supply 2 parameters, Oracle selects the version which accepts (and displays) 2 parameters:

SQL> set serveroutput on
SQL> create or replace package package1 is
  2  procedure procedure1
  3  (parameter1 in number);
  4  procedure procedure1
  5  (parameter1 in number,
  6   parameter2 in number);
  7  end package1;
  8  /
 
Package created.
 
SQL> create or replace package body package1 is
  2  procedure procedure1
  3  (parameter1 in number)
  4  is
  5  begin
  6  dbms_output.put_line('parameter1 = '||parameter1);
  7  end;
  8  procedure procedure1
  9  (parameter1 in number,
10   parameter2 in number)
11  is
12  begin
13  dbms_output.put_line('parameter1 = '||parameter1);
14  dbms_output.put_line('parameter2 = '||parameter2);
15  end;
16  end package1;
17  /
 
Package body created.
 
SQL> exec package1.procedure1(1);
parameter1 = 1
 
PL/SQL procedure successfully completed.
 
SQL> exec package1.procedure1(1,2);
parameter1 = 1
parameter2 = 2
 
PL/SQL procedure successfully completed.
 
SQL>
Viewing all 330 articles
Browse latest View live