Showing posts with label ORA-02097. Show all posts
Showing posts with label ORA-02097. Show all posts

Tuesday, March 31, 2015

Recursion in Oracle 12

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>

Sunday, August 19, 2012

rman Backup and Recovery - example 2

Recovery Manager stores backups at the location specified by the db_recovery_file_dest initialisation parameter. At the start of this example, which I tested on Oracle 11.2, my database had no db_recovery_file_dest details:

SQL> l
  1  select name, nvl(value,'NULL')
  2  from v$parameter
  3* where name like 'db_recovery_file_dest%'
SQL> /

NAME                           NVL(VALUE,'NULL')
------------------------------ --------------------
db_recovery_file_dest          NULL
db_recovery_file_dest_size     0

SQL>

So, when I used rman to do a backup, Oracle put the files it produced in $ORACLE_HOME/dbs instead. This has the potential to fill up $ORACLE_HOME so you must not do it. Notice how you can use rman to shutdown and startup mount the database:

Solaris > rman nocatalog target /

Recovery Manager: Release 11.2.0.1.0 - Production on Fri Aug 17 14:48:59 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

connected to target database: ANDREW01 (DBID=385736687)
using target database control file instead of recovery catalog

RMAN> shutdown

database closed
database dismounted
Oracle instance shut down

RMAN> startup mount

connected to target database (not started)
Oracle instance started
database mounted

Total System Global Area     417669120 bytes

Fixed Size                     2148672 bytes
Variable Size                314578624 bytes
Database Buffers              96468992 bytes
Redo Buffers                   4472832 bytes

RMAN> backup database;

Starting backup at 17-AUG-12
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=156 device type=DISK
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=/database/Andrew/ANDREW01/system01.dbf
input datafile file number=00002 name=/database/Andrew/ANDREW01/sysaux01.dbf
input datafile file number=00005 name=/database/Andrew/ANDREW01/users2.dbf
input datafile file number=00003 name=/database/Andrew/ANDREW01/undotbs01.dbf
channel ORA_DISK_1: starting piece 1 at 17-AUG-12
channel ORA_DISK_1: finished piece 1 at 17-AUG-12
piece handle=/oracle/app/oracle/product/11.2.0/dbs/03nisji9_1_1 tag=TAG20120817T145048 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:35
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
including current SPFILE in backup set
channel ORA_DISK_1: starting piece 1 at 17-AUG-12
channel ORA_DISK_1: finished piece 1 at 17-AUG-12
piece handle=/oracle/app/oracle/product/11.2.0/dbs/04nisjjc_1_1 tag=TAG20120817T145048 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 17-AUG-12

RMAN>

I tried to set db_recovery_file_dest by itself but failed:

SQL> l
  1  alter system set
  2* db_recovery_file_dest = '/database/Andrew'
SQL> /
alter system set
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because
specified value is invalid
ORA-19802: cannot use DB_RECOVERY_FILE_DEST without
DB_RECOVERY_FILE_DEST_SIZE

SQL>

The ORA-02097 message is slightly misleading as the parameter supplied is not invalid. The real problem is shown by the ORA-19802 message. I set db_recovery_file_dest_size to an appropriate value:

SQL> l
  1  alter system
  2* set db_recovery_file_dest_size = 4g
SQL> /

System altered.

SQL>

Then I was able to set db_recovery_file_dest successfully:

SQL> l
  1  alter system set
  2* db_recovery_file_dest = '/database/Andrew'
SQL> /

System altered.

SQL>

Friday, April 15, 2011

License_max_users

This was tested on an Oracle 10 database.

The license_max_users parameter determines how many users you can have in a database. How you set this parameter depends on your licensing agreement with Oracle.

If it is zero, you can create as many users as you want:

SQL> l
  1  select value from v$parameter
  2* where name = 'license_max_users'
SQL> /


VALUE
----------
0


SQL>

It is not relevant at the session level so you cannot change it there:

SQL> l
  1* alter session set license_max_users = 10
SQL> /
alter session set license_max_users = 10
                  *
ERROR at line 1:
ORA-02096: specified initialization parameter is not
modifiable with this option
SQL> 

You cannot set license_max_users lower than the number of users currently in a database:

SQL> select count(*) from dba_users;

  COUNT(*)
----------
        22


SQL> alter system set license_max_users = 21;
alter system set license_max_users = 21
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because
specified value is invalid
ORA-00035: LICENSE_MAX_USERS cannot be less than
current number of users


SQL> alter system set license_max_users = 22;

System altered.

SQL>

And if you try to create more users once you have reached the limit imposed by license_max_users, that will fail too:

SQL> create user fred identified by bloggs;
create user fred identified by bloggs
                               *
ERROR at line 1:
ORA-01985: cannot create user as LICENSE_MAX_USERS
parameter exceeded


SQL>

And a message goes to your alert log:

Create user disallowed, current users equal maximum (22)