Yearly Archives: 2020

Why PGA_AGGREGATE_LIMIT appears to be set, when it is not?

Today I had to explain why the pga_aggregate_target was showing a value, but one does not have to care about it most of the cases. Here the same explanation.

When doing:

SQL> show parameter pga

NAME                                 TYPE                                         VALUE
------------------------------------ -------------------------------------------- ----------------------
pga_aggregate_limit                  big integer                                  3000M
pga_aggregate_target                 big integer                                  1G

One would think that pga_aggregate_target is set to 3000M. However when one checks on the spfile, there is nothing defined:


Strange behaviours on setting PDB parameters 3

[Tests performed on Oracle 19.8]

All started when I wanted to create a query to check which parameters are set on a PDB and the difference from the CDB$ROOT container.

set pages 110
col pdb_name for a10 
col name for a30 
col value for a20
col pdb_value for a20
col root_value for a20
col source for a10
select a.pdb_name,, a.value PDB_VALUE, b.value ROOT_VALUE,source from
  (select pdb_name,name,value,a.con_id, decode(ismodified,'MODIFIED','PDB SPFILE','PDB$SEED') SOURCE 
   from v$system_parameter a left join dba_pdbs b on (a.CON_ID=b.pdb_id)
   where a.con_id>2 and (ismodified='MODIFIED' or isdefault='FALSE')) a,
  (select 'CDB$ROOT' pdb_name,name,value,con_id,null
   from v$system_parameter where con_id=0) b
where and a.con_id>2
order by 1,2;

But I know there is also one view called pdb_spfile$ that would show the parameters on the PDB pseudo-spfiles:

col pdb_name for a10 
col name for a20
col value$ for a20
select pdb_name,name,value$ 
from pdb_spfile$ left join dba_pdbs on (CON_UID=pdb_uid) 
where con_id>2 
and bitand(nvl(spare2,0),1)=0
order by name;

The V$SYSTEM_PARAMETER is well documented, while the PDB_SPFILE$ is not.

A slight more complete query to check parameters which are not set the same between cdb$root and the PDB is this one:

with pdb_params as (select pdb_name,name,trim(both '''' from value$) value$ 
                                   from pdb_spfile$ left join dba_pdbs on (CON_UID=pdb_uid)
                                   where con_id>1 and bitand(nvl(spare2,0),1)=0 ),
        cdb_params as (select name, value,inst_id,con_id from gv$parameter ),
        spfile_params as (select name,value, sid from v$spparameter where isspecified='TRUE')
  select pdb_name,, value$ pdb_value, cdb_params.value root_value, spfile_params.value spfile_value
    from pdb_params, cdb_params, spfile_params
    where and
        and (value$!=cdb_params.value or value$!=spfile_params.value)
union all 
  select case when sys_context('USERENV','CON_NAME') !='CDB$ROOT' then 'CALL THIS SCRIPT FROM CDB$ROOT' end pdb_name,
        null,null,null,null from dual
order by 1,2;

Now, the set or unset parameters do not work the same way, as I expected, it trigger some strange behaviours.


HugePages not used when starting DB with srvctl (but works with sqlplus)

Once again I end up with my clients database swapping. Why? After quick investigation, could see that HugePages were not used on the last restart of the database.

oracle@myvm1:./trace/ [oracle19] grep -B1 -A4 PAGESIZE alert*.log
        4K       Configured              10              10        NONE
     2048K           247816            8193            8193        NONE
        4K       Configured              10         4186122        NONE
     2048K           202479            8193              17        NONE

Why was that? I did use a normal start command:

oracle@myvm1:./trace/ [oracle19] srvctl start database -db mydb

Let’s put the context. This is a Oracle Restart server, with separation between oracle and grid users.


Get unlock from PDB Lockdown profiles

PDB Lockdown profiles allow, on a multitenant database, to limit what a user can do inside a PDB.

One use case is when we want to avoid high privileged users (like Application DBAs) to perform ALTER SYSTEM or ALTER SESSION commands.

Quickly we would think we can do a PDB Lockdown profile like:

SQL> create lockdown profile lock_test;
SQL> alter lockdown profile lock_test disable statement=('ALTER SESSION');
SQL> alter lockdown profile lock_test disable statement=('ALTER SYSTEM');

The problem of this simple profile is that we can lock ourselves, also as common user, inside the lock profile.

Image that you want to enable this profile on several PDBs:

SQL> alter session set container=pdb01;
Session altered.

SQL> alter system set pdb_lockdown=lock_test;
System altered.

SQL> alter session set container=samplepdb;
ORA-01031: insufficient privileges

Oups, you cannot anymore change the active container!


Which OPatch to use? One OPatch version fits (almost) all.

The download page of Oracle OPatch has quite some room for improvement: put some ‘order by’ on the version and platform would be welcome. Also, make clear that there are very few versions of it.

In fact, for database, there are just two versions of OPatch! One OPatch version that covers all database supported versions from 12.1 to 20c. For paid long-term supported Oracle 11.2 there is another version.

So, in summary, here the OPatch version you need to patch your DBs:

Oracle Database versionOPatch version

The download link is this one:

For Enterprise Manager (middleware) there is another OPatch version, 13.9.x which I don’t have experience with.

The information about which OPatch versions is needed to apply the Database RU, RUR, is now part of the Patch Availability Document. For instance for OCtober 2020, this is what we can see:

Note 1: For Enterprise Manager (middleware) there is another OPatch version, 13.9.x which I don’t have experience with.

Note 2 – for Oracle guys out there: when we see the current size of the Release Updates, maybe it would be worth to include the latest version of OPatch within it. It would not increase so much the size and avoid the need of checking if we have the latest OPatch.

How to reclaim storage space on Oracle Autonomous Database

Man shall pay only for what it uses. This is also a motto of the Cloud and Oracle with second-level billing pushes this model.

Concerning disk space, however, it is not always easy. While terabyte prices are getting cheaper, sometimes you make a big cleanup of your database and then you would like to pay only for what is being used.

On Oracle Autonomous Databases it is the sum of datafiles size that counts.

Image now that you have a huge table and then drop it. The datafile space is not recovered.

In order to recover space you need:

  • Purge the recycle bin:

SQL> purge dba_recyclebin

  • reduce size of DATA tablespace datafile

SQL> alter database datafile <file_id> resize yyyM;

Now, this will be possible only if there are no extents used at the end of the datafile. Otherwise, one can try to alter table <table_name> move online; and then alter tablespace <tbs_name> coalesce; but this is not sure to help.

During my tests I only had one table, which made things easier.

Let’s hope that Oracle either changes the way to calculate the space used or provides a way to (continuous) defragment a datafile and make the size dynamic.

To check the storage used on Autonomous Database and find the datafile file_id, you can run the following query:

-- Get Space used by tablespace and file_id
select TBS "File_ID-Tablespace",
  round(sum(bytes)/1024/1024/1024,2) USED_GB,
  round(sum(bytes)/max(PROPERTY_VALUE)*100) PCT 
  (select file_id||'-'||tablespace_name TBS, bytes 
    where tablespace_name!='SAMPLESCHEMA'),
group by rollup(TBS);

------------------ ------- --- 
3252-SYSTEM           0.41   2 
3253-SYSAUX           3.16  16 
3254-UNDOTBS1         0.44   2 
3255-DATA              0.1   0 
3256-DBFS_DATA         0.1   0 
                       4.2  21 

-- Get Total space used by DB
select round(USED_BYTES/1024/1024/1024,2) USED_GB,
  round(MAX_BYTES/1024/1024/1024,2) MAX_GB,
  (select sum(BYTES) USED_BYTES
    from DBA_DATA_FILES 

------- ------ -------- 
    4.2     20    21.01 


Oracle Cloud: what parameters make ATP different from ADW?

Using the Free Tier of Oracle Cloud I created one Autonomous DB of each type – one Autonomous Transaction Processing and one Autonomous Data Warehouse (Autonomous JSON are not yet available). Then did run

select name, display_value
from v$parameter
where isdefault='FALSE'
order by 1;

on each of the DBs, I got the follow differences (empty means not set):


Both the databases (PDB) share the same Container (CDB).

I did check also

select *
from database_properties;

but there are no initial state differences.

Something I found interesting. I had a 2-month old ATP when I created the ADW. Immediately I saw that my old ATP was not using ASM, compared to the ADW, also that ADW was a cluster DB while the old ATP was single instance.

I recreated the ATP to check if this remained. But no. My new ATP was co-located on the same database as the ADW, so parameters are mostly the same as we could see above.

For historical reasons, I leave here the parameter changes between ATP created in June and end-August 2020. For paths, only the differences are highlighted:

parameterATP June 2020ATP August 2020

Oracle 11.1 on Windows – ORA-02778

I’ve a funny challenge these days:

Recover a Oracle on Windows installation. I’ve all files in an external drive and I’m trying to make the DB to run on my laptop.

  • I’ve copied to my local disk;
  • Added the entries to the registry that found necessary
  • Re-created the Inventory
  • Re-created a init file with correct locations from the spfile

Now I had still had the error:

SQL> startup nomount
ORA-02778: Name given for the log directory is invalid

Nothing on the logs, all directories mentioned on pfile exist and are writable.

I’ve downloaded the Microsoft ProcessMonitor, configured to trace only Oracle company processes and looked what it tried to read.

Finally I found the culprit: %ORACLE_HOME%\RDBMS\log was missing. Just the log subfolder.

This was during the xcopy to the local disk, I excluded all “log” files, as there were some huge ones. Unfortunately it also excluded this folder. Now looks better:

SQL> startup nomount
ORACLE instance started.

Total System Global Area 1720328192 bytes
Fixed Size                  2130160 bytes
Variable Size             989859600 bytes
Database Buffers          721420288 bytes
Redo Buffers                6918144 bytes

SQL query for queue table with priorities 6

Queue tables are used to take care of events. There is a mechanism that insert rows and another that takes care of the existing rows, usually deleting them at the end.

When possible one should use Oracle Advanced Queuing mechanism which takes care of managing the queue and a simple request will give you the next in the line.

Some applications develop their own queuing systems and it is a good way to learn how queue works.

Imagine a table with a list of elements and two specific columns:

  • order of arrival
  • priority

The first to be served is the one that, having the highest priority, was the first to arrive.