11.2 AQ – Messages stuck in PROCESESED,WAIT State

I had been working today on AQ issue where messages were not moving from WAIT to READY State.This was on 11.2.0.3 database running on RHEL5u6(64 bit). I thought of quickly documenting it for easy reference
When you enqueue record, you can specify delay after which record should be ready for dequeue.
During this time, MSG_STATE is in ‘WAIT’ state, which changes to ‘READY’ state after current time reaches delay timestamp.All the stuck records were having delay_timestamp past current time.This can be verified by querying AQ$Queue_table.

Below example , you see that MSG_ID ‘D2DA56B9746E2E59E043096F93452D8A‘ has delay_timestamp of ’10-JAN-13 05.42.07.835125 AM’ which is less then current time ( 9:52 AM)

 09:52:00 SQL > select msg_id,msg_state,enq_timestamp,delay_timestamp from AQ$TEST_QTABLE where rownum <5;

 MSG_ID				 MSG_STATE  ENQ_TIMESTAMP		DELAY_TIMESTAMP
-------------------------------- ---------- ------------------------------ ------------------------------
D2DA56B94EF02E59E043096F93452D8A WAIT	    09-JAN-13 07.37.07.595334 AM   23-FEB-13 07.37.07.595334 AM
D2DA56B9746E2E59E043096F93452D8A WAIT	    09-JAN-13 07.42.07.835125 AM   10-JAN-13 05.42.07.835125 AM
D2DA56B94ED32E59E043096F93452D8A WAIT	    09-JAN-13 07.37.05.274447 AM   23-FEB-13 07.37.05.274447 AM
D2F1EDF5112D59A1E043096F93451A42 READY	    10-JAN-13 07.35.33.089265 AM   10-JAN-13 07.35.34.089265 AM

Along with this there were lot of messages in PROCESSED state.My first thought was that Retention for this queue was set to higher value, but on checking I found that it was set to 0. You can read my previous article on Retention and Processed messages in queue

V$AQ revealed that there were 2 more queues with Pending processed messages. As per documentation, Ready column should only show messages in READY state but here it included count for PROCESSED state too (Not sure if this is also bug)

select * from v$AQ where ready >1000
/
      QID    WAITING	   READY    EXPIRED AVERAGE_MSG_AGE TOTAL_WAIT AVERAGE_WAIT
--------- ---------- ---------- ---------- --------------- ---------- ------------
    79884	 1757	 6153814	  0	      92459 5.6914E+11	 92459.9842
    79892	    0	  183916	  0	   16643589 3.0610E+12	 16643589.1
    79894	    0	    1122	  0	    5420368 6081652896	    5420368

Verified that aq_tm_processes parameter was not set (Oracle recommends to unset it in 10g and above so that oracle can auto-tune it) and there were two processes running

$ps -ef|grep ora_q
oracle   25235     1  0 00:53 ?        00:00:00 ora_qmnc_alpha
oracle   25334     1  1 00:53 ?        00:04:26 ora_q001_alpha
oracle   26270     1  0 00:56 ?        00:00:00 ora_q002_alpha

To check further, I checked alert log for any ORA errors and found few entries for ORA-01405.

ORA-01405: fetched column value is NULL

On checking trace directory for queue process tracefile, same ora-01405 error was logged

kwqdlScanDeqLog during stmt fetch: retval -1, errnum 1405, errbuf ORA-01405: fetched column value is NULL

Checked Oracle MySupport and was able to locate note ID 1162862.1 – ORA-01405: Fetched Column Value Is Null For An Advanced Queue

In Oracle 11.2 a new dequeue log table named as AQ$_QT_L has been introduced which is used for storing message identifiers of committed dequeued operations on the queue.Due to bug 12899768 there are few message id with ‘00000000000000000000000000000000’ in this queue table which causes PROCESSED messages to get stuck.

Note 12899768.8 indicates that this is bug in 11.2.0.2 and 11.2.0.3 database

Symptoms include

– ORA-01405 errors for qmon process
– Lot of PROCESSED messages in queue
– Messages with message id’s like ‘00000000000000000000000000000000’

We need to either apply patch for this bug or set event ‘10852 trace name context forever, level 16384’
On searching for this event, came across Note 1365655.1 – Dequeue by msgid of a message in WAIT state does not work properly in 11.2

This note matched our main problem where messages are not changing state from WAIT to ready. This note also suggested setting event 10852 followed by database restart. To correct this issue we followed below steps

a)Stopped the Apps to prevent enqueue/dequeue. You can also stop it using dbms_aqadm.stop_queue() but this would generate errors in app.
b)deleted messages with msgid like ‘00000000000000000000000000000000’ from new queue table

delete from AQ$TEST_TABLE_L where msgid ='00000000000000000000000000000000';
commit;

c)Set event in spfile and restart database

conn / as sysdba
alter system set event='10852 trace name context forever, level 16384' scope=spfile;

After restart,messages with delay_timestamp older then current time changed state to READY and count in V$AQ started dropping indicating that qmon process was purging processed messages.

Using SQL commands on ADRCI

While working with ADRCI , I came to know that we can run normal SQL commands for some of the operation.e.g To display current purge policy , you can run select * from adr_control instead of show control.

adrci> desc ADR_CONTROL
Name                          Type            NULL?      
----------------------------- --------------- -----------
ADRID                         number                     
SHORTP_POLICY                 number                     
LONGP_POLICY                  number                     
LAST_MOD_TIME                 timestamp                  
LAST_AUTOPRG_TIME             timestamp                  
LAST_MANUPRG_TIME             timestamp                  
ADRDIR_VERSION                number                     
ADRSCHM_VERSION               number                     
ADRSCHMV_SUMMARY              number                     
ADRALERT_VERSION              number                     
CREATE_TIME                   timestamp

Since I am only interested in few columns, I can create a view

adrci> create view my_control as select SHORTP_POLICY,LONGP_POLICY,LAST_AUTOPRG_TIME,LAST_MANUPRG_TIME from ADR_CONTROL;

View MY_CONTROL Created

Now you can query this new view

adrci> select * from my_control;

ADR Home = /home/oracle/diag/rdbms/tintin/tintin1:
*************************************************************************
SHORTP_POLICY        LONGP_POLICY         LAST_AUTOPRG_TIME                        LAST_MANUPRG_TIME                        
-------------------- -------------------- ---------------------------------------- ---------------------------------------- 
720                  8760                 2012-12-27 23:09:47.140711 +00:00                                                
1 rows fetched

You can find the list of all metadata tables under ADR_HOME/metadata.

oradbdev01:tintin1:/home/oracle/diag/rdbms/tintin/tintin1/metadata>ls -ltr HM*
-rw-r----- 1 oracle dba   65536 Jan 13  2012 HM_INFO.ams
-rw-r----- 1 oracle dba   65536 Jan 13  2012 HM_FDG_SET.ams
-rw-r----- 1 oracle dba   65536 Jan 13  2012 HM_MESSAGE.ams
-rw-r----- 1 oracle dba   65536 Dec 27 23:09 HM_RECOMMENDATION.ams
-rw-r----- 1 oracle dba   65536 Dec 27 23:09 HM_FINDING.ams
-rw-r----- 1 oracle dba 9895936 Jan  3 05:44 HM_RUN.ams

We can run query on HM_RUN table like this

adrci> select RUN_ID,RUN_NAME,CHECK_NAME,MODE,START_TIME,END_TIME,STATUS from HM_RUN where rownum

I tried running substr command to format the column but this gives error 🙂

adrci> select RUN_ID,substr(RUN_NAME,1,20),CHECK_NAME,MODE,START_TIME,END_TIME,STATUS from HM_RUN where rownum <2;
DIA-48001: internal error code, arguments: [dbgrmdmmr_marshall_rec_null_terminate], [1], [8], [8], [], [], [], []

There is SET COLUMN text size command, but it sets length for all Text columns and can’t be used to size individual column. This is useful if you are querying big field like “Text” column of VIEW. e.g

adrci> set column text 100
adrci> select text from view where name='MY_CONTROL';

ADR Home = /home/oracle/diag/rdbms/tintin/tintin1:
*************************************************************************
TEXT                                                                                                 
---------------------------------------------------------------------------------------------------- 
select SHORTP_POLICY,LONGP_POLICY,LAST_AUTOPRG_TIME,LAST_MANUPRG_TIME from ADR_CONTROL;

Happy New Year – Goodbye 2012 and welcome 2013

It seems Mayan’s freaked out lot of people by not making 2013 calendar 🙂 Anyways our world survives and we will be entering 2013 in another 7 hours. So wishing all Oracle Community members a “Happy And Prosperous New Year

This year we have heard lot of buzz around “Big Data” and it seems to be gaining popularity in Data warehousing World.  Oracle will be releasing its Oracle 12c database next year with emphasis on Cloud features. Let’s wait and see what is in store for us.

This year’s annual wordpress stats report is out and we clocked 230,000 pageviews in 2012. We have not been active this year and have got most of the hits on older articles. We hope to improve it in coming year.

On personal front this was Wonderful year.  My younger sister got married this year,Saurabh was blessed with Baby Boy and Abhishek had a Sweet little Angel.

Btw I have moved this blog to Amazon AWS platform on trial basis. Will check for some time before posting my experience with it.

(In case you are wondering why there is Snow falling on screen, this is provided by wordpress upto 4th Jan and can be enabled in settings 🙂 )

Lost your Oracle Prometric-ID !!!

If you are creating your Pearson VUE  account and you have already passed some Oracle certifications earlier, you need to put your old Prometric id so that your old certifications at Prometric get merged automatically with the new Pearson account. But, if you forgot your old Prometric id, as happened to me, you can probably get it by raising SR with Oracle certification team at:

http://education.oracle.com/pls/eval-eddap-dcd/OU_SUPPORT_OCP.home?p_source=OCP .

I got my ID by raising SR at this link, for this, I provided my first name, last name and Date-of-Birth. Oracle did not ask any further questions and replied back with my testing-id   🙂

Upgrade Enterprise Manager Cloud Control 12.1.0.1 to 12.1.0.2

Oracle released 12.1.0.2 Enterprise Manager few days back and have released it for most of platforms.

You can directly upgrade Enterprise Manager Cloud Control 12c Release 1 (12.1.0.1) [with or without Bundle Patch 1] to 12.1.0.2
There are no pre patches required for this. But this upgrade requires considerable downtime. Oracle has termed this upgrade as 1-system upgrade approach which means that upgrades your Enterprise Manager Cloud Control on the same host—upgrades Oracle Management Service (OMS) on the same host and Oracle Management Repository (Management Repository) in the existing database.

I decided to upgrade my test EM 12c setup running on RHEL 5.6 x86_64 bit with single OMS and 11.2.0.3 database.Whole upgrade went fine without any major issues. To get started you need to download the software from here

I will be upgrading 12.1.0.1 running on Linux x86_64 bit. You can download the software from
http://download.oracle.com/otn/linux/oem/121020/em12cr2_linux64_disk1.zip
http://download.oracle.com/otn/linux/oem/121020/em12cr2_linux64_disk2.zip
http://download.oracle.com/otn/linux/oem/121020/em12cr2_linux64_disk3.zip

Once all files are downloaded, unzip them in single directory location.
To start the installation , run the runInstaller

./runInstaller

First screen asks for MOS details. You can choose to ignore it by unchecking box and click next.This will generate warning, press ok and click next

Next screen is related to software updates. You can “search for updates” and then select “My Oracle Support” to download the updates.We opted to “skip” this part.

On pre-requisite screen, installer checks whether your environment meets all the minimum requirements for a successful upgrade.
If some checks result in Warning or Failed status, then investigate and correct the problems before you proceed with the upgrade.

On the Installation Types screen, select Upgrade an Existing Enterprise Manager System, then select One System Upgrade. Then, select the OMS home you want to upgrade.

Next select the location for middleware home. 12.1.0.2 is out of place upgrade,so you need to specify new middleware home (without EM grid control) or a new home.

Next screen you pass connection details for EM repository.After you enter sys/sysman password it prompts you to stop oms

Stop the OMS using emctl utility.

$OMS_HOME/bin/emctl stop oms
Oracle Enterprise Manager Cloud Control 12c Release 12.1.0.1.0
Copyright (c) 1996, 2011 Oracle Corporation. All rights reserved.
Stopping WebTier...
WebTier Successfully Stopped
Stopping Oracle Management Server...
Oracle Management Server Successfully Stopped
Oracle Management Server is Down

Once OMS is stopped, we press ok on message and again click Next.Installer complains for pre-requisite check for emkey .This can be corrected by copying emkey to database repository.

Syntax for this is

$/bin/emctl config emkey -copy_to_repos_from_file -repos_host-repos_port-repos_sid-repos_user[-repos_pwd] -emkey_file/sysman/config/emkey.ora

I have replaced this with actual values for my setup

[oracle@oradbdev04]~% /home/oracle/Middleware/oms/bin/emctl config emkey -copy_to_repos_from_file -repos_host oradbdev04 -repos_port 1521 -repos_sid em12c -repos_user sysman -repos_pwd oracle123 -emkey_file /home/oracle/Middleware/oms/sysman/config/emkey.ora 
Oracle Enterprise Manager Cloud Control 12c Release 12.1.0.1.0  
Copyright (c) 1996, 2011 Oracle Corporation.  All rights reserved.
Enter Admin User's Password : 
The EMKey has been copied to the Management Repository. This operation will cause the EMKey to become unsecure.
After the required operation has been completed, secure the EMKey by running "emctl config emkey -remove_from_repos".

Next screen asks you to disable CBO gather stats job and set job_queue_processes to 0. You can press “Yes” and installer will automatically make changes for you.

We got next screen informing about some more pre-requisites which are not mandatory. We clicked ok and skipped them

On the Plug-In Upgrade screen, it will list plugins which are currently installed and new version post upgrade. Review them and click next

On the Plug-In Deployment screen, select the optional plug-ins you want to deploy in addition to the plug-ins that will automatically be upgraded while upgrading the OMS. ( I forgot to take screenshot of this page)

On the Extend WebLogic Server Domain screen , validate Adminserver details and enter WebLogic user account password.This is required to create a new WebLogic domain (GCDomain) on the same port and host name as the AdminServer used by the earlier release of the OMS you are upgrading.

We also need to enter new location for OMS instance base directory. As per oracle docs, it can be either inside or outside middleware home. Recommended approach is to keep it inside middleware home. We decided to use /home/oracle/product/middleware/gc_inst

You are next presented with summary screen and asked to click next

Next screen shows installation progress. This took nearly 1.5 hours.

Last step is to run $OMS_HOME/allroot.sh as root user

[root@oradbdev04 oms]# ./allroot.sh
Starting to execute allroot.sh .........
Starting to execute /home/oracle/product/middleware/oms/root.sh ......
 Running Oracle 11g root.sh script...
The following environment variables are set as:
 ORACLE_OWNER= oracle
 ORACLE_HOME= /home/oracle/product/middleware/oms
Enter the full pathname of the local bin directory: [/usr/local/bin]:
 The file "dbhome" already exists in /usr/local/bin. Overwrite it? (y/n)
 [n]:
 The file "oraenv" already exists in /usr/local/bin. Overwrite it? (y/n)
 [n]:
 The file "coraenv" already exists in /usr/local/bin. Overwrite it? (y/n)
 [n]:
Entries will be added to the /etc/oratab file as needed by
 Database Configuration Assistant when a database is created
 Finished running generic part of root.sh script.
 Now product-specific root actions will be performed.
 /etc exist
 /home/oracle/product/middleware/oms
 Finished execution of /home/oracle/product/middleware/oms/root.sh ......

 

Press ok on installer and we are finished with 12c installation.

Final screen lists down the url to access Enterprise manager grid control (12.1.0.2) and Weblogic Admin server.


Since one system upgrade only upgrades OMS and repository , we are still left with upgrading our central management agent.

1)Ensure that the Management Agents you want to upgrade are up and running.
2)Ensure that the Management Agents you want to upgrade are secure.

From the Setup menu, select Manage Cloud Control, then select Upgrade Agents. Click Add, select the Management Agents you want to upgrade, then click Select.

Select the Central management agent (which in this case is oradbdev04) and submit the job

Since we do not have root privileges, we have to run the $AGENT_BASE_DIR/core/12.1.0.2.0/root.sh script on the host after the upgrade.

 

You can monitor the agent install process

Note that oracle installs the agent in same base directory but creates new directory 12.1.0.2.0.

Before upgrade
/home/oracle/Middleware/agent/core/12.1.0.1.0

Post upgrade
/home/oracle/Middleware/agent/core/12.1.0.2.0

If you check agent status, you will find that oracle has automatically started the agent from new oracle home.

Run root.sh to complete the upgrade process

[root@oradbdev04 12.1.0.2.0]# ./root.sh
Finished product-specific root actions.
/etc exist
Finished product-specific root actions.

You can now upgrade the other management agent manually on the targets. Agent 12.1.0.1 is compatible with EMGC (12.1.0.2)

References

Oracle® Enterprise Manager Cloud Control Upgrade Guide12c Release 2 (12.1.0.2)

Limiting I/O and CPU resources using 11g Oracle Resource Manager

Recently I was working on using Oracle DBMS_RESOURCE_MANAGER to limit resources usage by read-only queries. This was required to prevent long running ad-hoc and poorly written queries.Instead of writing custom sql /script to kill long running session, we decided to utilize Oracle Database Resource Manager.
We decided using elapsed_time as criteria for cancelling sql.But during tests we found out that any I/O bound query didn’t kill after specified switch_time.
On checking My Oracle Support, we came across Note ID 1485199.1, which discussed the exact situation faced by us.

As per note , starting 11.2 oracle has fixed the Unpublished Bug 8202097 where some waits were included in the active time and could trigger switch_time early. Due to this fix, switch_time applies for the execution time (in CPU seconds) and not for the total elapsed time (which includes wait times also) of the query.

What this means is that any query which is waiting on wait class other then CPU (e.g I/O ) will not be killed based on switch time.Switch_time applies only to time spent on CPU. Waits are not included.

Checking Oracle 11g Documentation, we found that Oracle had introduced new parameter in create_plan_directive named switch_io_megabytes which can be used to cancel sql after specified I/O limit is reached.
We used following code to create resource manager plan with following directives

a)Limit Cpu time to 3600 s
b)Limit Parallelism to 4
c)Limit I/O to 20000Mb (~20G)

begin
sys.dbms_resource_manager.clear_pending_area();
sys.dbms_resource_manager.create_pending_area();
sys.dbms_resource_manager.create_consumer_group(CONSUMER_GROUP=>'CPU_IO_LIMIT_GRP',
COMMENT=>'Consumer group for RO_USER to limit parallelism,I/O and CPU Time');
sys.dbms_resource_manager.set_consumer_group_mapping(attribute => DBMS_RESOURCE_MANAGER.ORACLE_USER,
value => 'RO_USER',consumer_group =>'CPU_IO_LIMIT_GRP');

-- Create resource plan:
sys.dbms_resource_manager.create_plan(PLAN=> 'CPU_IO_LIMIT',COMMENT=>'Cancel Sql plan for RO_USER');

--Need to create plan_directive
--Limiting parallelism to max 4, I/O Limit to 10000Mb and CPU_time to 3600 sec
sys.dbms_resource_manager.create_plan_directive(
PLAN=> 'CPU_IO_LIMIT',
GROUP_OR_SUBPLAN=>'CPU_IO_LIMIT_GRP',
COMMENT=>'Kill statement after exceeding 3600 sec , limit parallelism to max 4 and limit i/o to 20000M ',
PARALLEL_DEGREE_LIMIT_P1 => 4,
SWITCH_GROUP=>'CANCEL_SQL',
SWITCH_TIME=>3600,
SWITCH_IO_MEGABYTES=>20000,
SWITCH_ESTIMATE=>false
);

--Its compulsory to specify directive for OTHER_GROUPS else this will fail
dbms_resource_manager.create_plan_directive(PLAN=> 'CPU_IO_LIMIT',GROUP_OR_SUBPLAN=>'OTHER_GROUPS',CPU_P1=>100);
sys.dbms_resource_manager.validate_pending_area;
sys.dbms_resource_manager.submit_pending_area;
end;
/

--Grant RO_USER to switch group
exec dbms_resource_manager_privs.grant_switch_consumer_group('RO_USER','CPU_IO_LIMIT_GRP',false);
--Set initial group for RO_USER to CPU_IO_LIMIT_GRP
exec dbms_resource_manager.set_initial_consumer_group('RO_USER','CPU_IO_LIMIT_GRP');

To enable resource manager plan

ALTER SYSTEM SET RESOURCE_MANAGER_PLAN ='CPU_IO_LIMIT';

We started query on big table and specified parallel degree as  8

alter session force parallel query parallel 8;

select /*+ full(a)  */ count(*) from big_table a;

From V$px_session we can verify that we requested 8 degree but we are getting only 4 due to resource manager plan directive.

INST_ID Username    QC/Slave   Slave Set  SID    QC SID Requested DOP Actual DOP MODULE                SQL_ID      EVENT             STATUS
---------- ------------ ---------- ---------- ------ ------ ------------- ---------- ------------------------------ ------------- ------------------------- --------
2  - p000    (Slave)    1          390    579        8       4 SQL*Plus                7fgfym909mqmn direct path read        ACTIVE
2    RO_USER    QC                  579    579                 SQL*Plus                7fgfym909mqmn PX Deq: Execute Reply     ACTIVE
2  - p001    (Slave)    1          580    579        8       4 SQL*Plus                7fgfym909mqmn direct path read        ACTIVE
2  - p002    (Slave)    1          772    579        8       4 SQL*Plus                7fgfym909mqmn direct path read        ACTIVE
2  - p003    (Slave)    1          966    579        8       4 SQL*Plus                7fgfym909mqmn direct path read        ACTIVE

I was monitoring the resource usage using v$rsrc_session_info in separate session

SELECT s.sid sess_id, g.name consumer_group,
s.state, s.consumed_cpu_time cpu_time, s.cpu_wait_time, s.queued_time,(s.CURRENT_SMALL_READ_MEGABYTES+s.CURRENT_LARGE_READ_MEGABYTES) read_MB,(s.CURRENT_SMALL_WRITE_MEGABYTES+s.CURRENT_LARGE_WRITE_MEGABYTES) write_mb
FROM v$rsrc_session_info s, v$rsrc_consumer_group g
WHERE s.current_consumer_group_id = g.id and g.name='CPU_IO_LIMIT_GRP';

After some time our original query got cancelled with following error

ERROR at line 1:
ORA-12801: error signaled in parallel query server P001, instance prod02:orcl02 (2)
ORA-56720: I/O data limit exceeded - call aborted

Just before failure , v$rsrc_session_info output looked like this indicating that we reached 20000M limit specified for I/O

SESS_ID CONSUMER_GROUP            STATE     CPU_TIME CPU_WAIT_TIME QUEUED_TIME    READ_MB     WRITE_MB
---------- -------------------------------- ---------- ---------- ------------- ----------- ---------- ----------
1347 CPU_IO_LIMIT_GRP        WAITING           62          0       0         1        0
1154 CPU_IO_LIMIT_GRP        WAITING        38050          0       0     18707        0
774 CPU_IO_LIMIT_GRP        WAITING        37400          0       0     19871        0
582 CPU_IO_LIMIT_GRP        WAITING        36267          0       0     19073        0
10 CPU_IO_LIMIT_GRP        WAITING        41515          0       0     19843        0

You can notice that when we specify parallelism, each process had individual 20000M I/O limit.
Previous query was only read operation and we were wondering if this I/O limit applied to both read/write operation. To confirm this we ran query with 4 table join doing merge cartersian join (This was one of query which used 100G of temp tablespace and prompted us to start this exercise 🙂

To remove the plan, we have to unset resource_manager_plan parameter and then delete it using following code

ALTER SYSTEM SET RESOURCE_MANAGER_PLAN ='';
begin
sys.dbms_resource_manager.clear_pending_area();
sys.dbms_resource_manager.create_pending_area();
sys.dbms_resource_manager.delete_plan_cascade ('CPU_IO_LIMIT');
sys.dbms_resource_manager.submit_pending_area();
end;
/

We recreated plan with 10000M as new I/O limit and ran the query.(We can also use dbms_resource_manager.update_plan_directive to update the settings).

Meanwhile I used new sql to get single /multi block read/write I/O along with totals.

col state for a10
col CONSUMER_GROUP for a20
SELECT s.sid sess_id, g.name consumer_group,
s.state, s.consumed_cpu_time cpu_time, s.cpu_wait_time, s.queued_time,s.CURRENT_SMALL_READ_MEGABYTES S_RIO,s.CURRENT_LARGE_READ_MEGABYTES M_RIO,s.CURRENT_SMALL_WRITE_MEGABYTES S_WIO,s.CURRENT_LARGE_WRITE_MEGABYTES M_WIO,(s.CURRENT_SMALL_READ_MEGABYTES+s.CURRENT_LARGE_READ_MEGABYTES) read_MB,(s.CURRENT_SMALL_WRITE_MEGABYTES+s.CURRENT_LARGE_WRITE_MEGABYTES) write_mb
FROM v$rsrc_session_info s, v$rsrc_consumer_group g
WHERE s.current_consumer_group_id = g.id and g.name='CPU_IO_LIMIT_GRP';

Before failure we had following output from v$rsrc_session_info with 3341M as reads and 6614 writes (total of 9955M ~10000M). It confirms that I/O limit here includes both read/write I/O

SESS_ID CONSUMER_GROUP    STATE         CPU_TIME CPU_WAIT_TIME QUEUED_TIME      S_RIO    M_RIO       S_WIO      M_WIO    READ_MB     WRITE_MB
---------- -------------------- ---------- ---------- ------------- ----------- ---------- ---------- ---------- ---------- ---------- ----------
199 CPU_IO_LIMIT_GRP    WAITING        104786          0          0        233     3108         203       6295      3341         6498

SESS_ID CONSUMER_GROUP    STATE         CPU_TIME CPU_WAIT_TIME QUEUED_TIME      S_RIO    M_RIO       S_WIO      M_WIO    READ_MB     WRITE_MB
---------- -------------------- ---------- ---------- ------------- ----------- ---------- ---------- ---------- ---------- ---------- ----------
199 CPU_IO_LIMIT_GRP    RUNNING        106749          0          0        233     3108         207       6407      3341         6614

One last test was to test for queries exceeding specified CPU Time. To perform this test we altered switch_time to 120 seconds and re-ran the query involving joins.After nearly 5 minutes, our sql got killed with following error

ORA-00040: active time limit exceeded - call aborted
Elapsed: 00:04:47.13

--Resource usage
SESS_ID CONSUMER_GROUP    STATE         CPU_TIME CPU_WAIT_TIME QUEUED_TIME      S_RIO    M_RIO       S_WIO      M_WIO    READ_MB     WRITE_MB
---------- -------------------- ---------- ---------- ------------- ----------- ---------- ---------- ---------- ---------- ---------- ----------
199 CPU_IO_LIMIT_GRP    RUNNING        141184          0          0        236     3108         254       7885      3344         8139

Above query reported 140s as total consumed time even though we had specified 120 s.(Not sure if this is expected behavior as note 1485199.1 mentioned that it does not include any wait) Note that we used switch_group as CANCEL_SQL which cancels the running sql after limit is reached.In case you plan to kill the session, you need to use KILL_SESSION.

You would notice that we used switch_estimate to false . This parameter tells oracle to estimate the execution time before the operation starts.If you use switch_estimate to true  in above code, you will notice that it will kill the session immediately along with error message indicating which I/O limit was reached.

If you set switch_estimate to true and set max_est_exec_time which specifies the maximum execution time (in CPU seconds) allowed for a session. If the optimizer estimates that an operation will take longer than MAX_EST_EXEC_TIME, the operation is not started and ORA-07455 is issued.

You can notice that this is far better approach of enforcing limits rather then writing your own script/triggers. Some of advantages in this case were

a)Both the cases we got pretty informative error indicating that we are excluding specified limits.

b)Gave us control of limiting parallelism

c)Allows us to specify I/O based limits

We didn’t use cpu allocation in this case but you can also limit cpu available for users using mgmt_p1 (cpu_p1 ,etc are deprecated).In case you are planning to implement this in your production database with cancel_sql directive, I would recommend ensuring that it should not be application user else you will start experiencing unwanted results.