Call now: 252-767-6166  
Oracle Training Oracle Support Development Oracle Apps

 
 Home
 E-mail Us
 Oracle Articles
New Oracle Articles


 Oracle Training
 Oracle Tips

 Oracle Forum
 Class Catalog


 Remote DBA
 Oracle Tuning
 Emergency 911
 RAC Support
 Apps Support
 Analysis
 Design
 Implementation
 Oracle Support


 SQL Tuning
 Security

 Oracle UNIX
 Oracle Linux
 Monitoring
 Remote s
upport
 Remote plans
 Remote
services
 Application Server

 Applications
 Oracle Forms
 Oracle Portal
 App Upgrades
 SQL Server
 Oracle Concepts
 Software Support

 Remote S
upport  
 Development  

 Implementation


 Consulting Staff
 Consulting Prices
 Help Wanted!

 


 Oracle Posters
 Oracle Books

 Oracle Scripts
 Ion
 Excel-DB  

Don Burleson Blog 


 

 

 


 

 

 
 

Using Contexts to Store Global Data


Oracle Tips by Burleson Consulting

 

The following Tip is from the outstanding book "Oracle PL/SQL Tuning: Expert Secrets for High Performance Programming" by Dr. Tim Hall, Oracle ACE of the year, 2006:

An alternative to the previous method is to use contexts to store the global data.  A context is a set of application-defined attributes associated with a namespace that is linked to a managing package.  A context is created using the CREATE CONTEXT statement in which the namespace equates to the context name.

CREATE CONTEXT namespace USING package-name;

The managing package does not have to be present at the point when the context is created, but must be present before it is referenced.  The dbms_session.set_context procedure is used to associate name-value pairs with the context, but for security purposes this procedure can only be used from within the package associated with the context. 

Context attributes can be read using the sys_context function available from SQL and PL/SQL.  The following example uses this function to retrieve the current session identifier from the default userenv context.

SQL> SELECT SYS_CONTEXT('USERENV', 'SESSIONID') FROM dual;

SYS_CONTEXT('USERENV','SESSION
--------------------------------------------------------------------
328385

1 row selected.

To show how contexts can be used to cache global session data, the examples from the previous section using contexts instead of package variables will be recreated.  In order to do this, the CREATE ANY CONTEXT privilege must be granted to the owner of the context, and just for the purpose of this example, the CREATE TRIGGER privilege is also necessary.

GRANT CREATE ANY CONTEXT TO username;
GRANT CREATE TRIGGER TO username;

The global_context.sql script creates a context named global_context along with a supporting package specification, and the body named global_context_api referenced by the context.  It relies on the presence of the system_parameters table created previously using the create_cached_lookup_tab.sql script.  In addition it creates a logon trigger to initialize the package as soon as the session logon occurs.

global_context.sql

-- Create the context referencing global_api.
CREATE OR REPLACE CONTEXT global_context USING global_context_api;
-- Create the package specification and body to support the context.
CREATE OR REPLACE PACKAGE global_context_api AS
PROCEDURE set_parameter(p_name   IN  VARCHAR2,
                        p_value  IN  VARCHAR2);
PROCEDURE initialize;
END global_context_api;
/
SHOW ERRORS

CREATE OR REPLACE PACKAGE BODY global_context_api IS
-- -----------------------------------------------------------------
PROCEDURE set_parameter (p_name   IN  VARCHAR2,
                         p_value  IN  VARCHAR2) IS
-- -----------------------------------------------------------------
BEGIN
  DBMS_SESSION.set_context('global_context', p_name, p_value);
END set_parameter;
-- -----------------------------------------------------------------

-- -----------------------------------------------------------------
PROCEDURE initialize AS
-- -----------------------------------------------------------------
  l_audit_on  system_parameters.audit_on%TYPE;
  l_trace_on  system_parameters.trace_on%TYPE;
  l_debug_on  system_parameters.debug_on%TYPE;
BEGIN
  SELECT audit_on,
         trace_on,
         debug_on
  INTO   l_audit_on,
         l_trace_on,
         l_debug_on
  FROM   system_parameters;

  set_parameter(‘audit_on’, l_audit_on);
  set_parameter(‘trace_on’, l_trace_on);
  set_parameter(‘debug_on’, l_debug_on);
END initialize;
-- -----------------------------------------------------------------

END global_context_api;
/
SHOW ERRORS

-- Create trigger to initialize the collection.
CREATE OR REPLACE TRIGGER after_logon_trg AFTER
LOGON ON SCHEMA BEGIN
  global_context_api.initialize;
END;
/
SHOW ERRORS

The initialize procedure and trigger are only necessary for this example and is not a prerequisite for context usage in general.  The initialize procedure retrieves the data from the system_parameters table and sets this in the context.  In order for the following examples to work correctly, the context must be initialized by either reconnecting to the database or manually calling the initialize procedure.

SQL> EXEC global_context_api.initialize;
PL/SQL procedure successfully completed.

All context data for the current session can be displayed using the session_context view, as demonstrated by the session_context.sql script below.

session_context.sql

SET LINESIZE 200

COLUMN namespace FORMAT A20
COLUMN attribute FORMAT A20
COLUMN value FORMAT A20

SELECT namespace,
       attribute,
       value
FROM   session_context
ORDER BY namespace, attribute;

The output from this script shows that the context has been initialized as expected.

SQL> @session_context.sql

NAMESPACE            ATTRIBUTE            VALUE
-------------------- -------------------- --------------------
GLOBAL_CONTEXT       AUDIT_ON             Y
GLOBAL_CONTEXT       DEBUG_ON             N
GLOBAL_CONTEXT       TRACE_ON             N

3 rows selected.

SQL>

The global_context_api_test.sql script shows how the values of the context variables can be set and retrieved using the set_parameter procedure and the sys_context function.

global_context_api_test.sql

SET SERVEROUTPUT ON
BEGIN
  DBMS_OUTPUT.put_line('Show global data');
  DBMS_OUTPUT.put_line('audit_on: ' || SYS_CONTEXT('global_context', 'audit_on'));
  DBMS_OUTPUT.put_line('trace_on: ' || SYS_CONTEXT('global_context', 'trace_on'));
  DBMS_OUTPUT.put_line('debug_on: ' || SYS_CONTEXT('global_context', 'debug_on'));

  DBMS_OUTPUT.put_line('Reset global data');
  global_context_api.set_parameter('audit_on','N');
  global_context_api.set_parameter('trace_on','Y');
  global_context_api.set_parameter('debug_on','Y');
  DBMS_OUTPUT.put_line('audit_on: ' || SYS_CONTEXT('global_context', 'audit_on'));
  DBMS_OUTPUT.put_line('trace_on: ' || SYS_CONTEXT('global_context', 'trace_on'));
  DBMS_OUTPUT.put_line('debug_on: ' || SYS_CONTEXT('global_context', 'debug_on'));
END;
/

The results of this script clearly show that the global variables are both initialized and reset as expected.

SQL> @global_context_api_test.sql

Show global data
audit_on: Y
trace_on: N
debug_on: N
Reset global data
audit_on: N
trace_on: Y
debug_on: Y

PL/SQL procedure successfully completed.

The secure_global_context_api_body.sql script provides an alternate package body that includes validation within the set_parameter procedure to restrict access to the audit and trace variables and to validate the debug setting.

secure_global_context_api_body.sql

CREATE OR REPLACE PACKAGE BODY global_context_api IS

-- -----------------------------------------------------------------
PROCEDURE set_parameter (p_name   IN  VARCHAR2,
                         p_value  IN  VARCHAR2) IS
-- -----------------------------------------------------------------
BEGIN
  IF UPPER(p_name) IN ('AUDIT_ON', 'TRACE_ON') THEN
    RAISE_APPLICATION_ERROR(-20000, 'Alteration of ' || p_name || ' value is prohibited.');
  ELSIF UPPER(p_name) = 'DEBUG_ON'
  AND p_value NOT IN ('Y', 'N') THEN
    RAISE_APPLICATION_ERROR(-20001, 'debug_on must be set to Y or N.');
  END IF;   

  DBMS_SESSION.set_context('global_context', p_name, p_value);
END set_parameter;
-- -----------------------------------------------------------------

-- -----------------------------------------------------------------
PROCEDURE initialize AS
-- -----------------------------------------------------------------
  l_audit_on  system_parameters.audit_on%TYPE;
  l_trace_on  system_parameters.trace_on%TYPE;
  l_debug_on  system_parameters.debug_on%TYPE;
BEGIN
  SELECT audit_on,
         trace_on,
         debug_on
  INTO   l_audit_on,
         l_trace_on,
         l_debug_on
  FROM   system_parameters;

  DBMS_SESSION.set_context('global_context', 'audit_on', l_audit_on);
  DBMS_SESSION.set_context('global_context', 'trace_on', l_trace_on);
  DBMS_SESSION.set_context('global_context', 'debug_on', l_debug_on);
END initialize;
-- -----------------------------------------------------------------

END global_context_api;
/
SHOW ERRORS

While running the global_context_api_test.sql script against this alternate package body, an error results when an attempt is made to amend the audit variable.

SQL> @global_context_api_test.sql
Show global data
audit_on: Y
trace_on: N
debug_on: N
Reset global data
BEGIN

ERROR at line 1:
ORA-20000: Alteration of audit_on value is prohibited.
ORA-06512: at "TEST.GLOBAL_CONTEXT_API", line 9
ORA-06512: at line 8

The global_context_comparison.sql script compares the performance of a database query with a context read.

global_context_comparison.sql

-- *****************************************************************
-- Parameters:  1) loops - The number of loop iterations.
-- *****************************************************************

SET VERIFY OFF
SET SERVEROUTPUT ON
DECLARE
  l_start     NUMBER;
  l_loops     NUMBER := &1;
  l_debug_on  system_parameters.debug_on%TYPE;
BEGIN
  -- Time the DB lookup.
  l_start := DBMS_UTILITY.get_time;

  FOR i IN 1 .. l_loops LOOP
    SELECT debug_on
    INTO   l_debug_on
    FROM   system_parameters;
  END LOOP; 

  DBMS_OUTPUT.put_line('DB Lookup (' || l_loops || ' rows)     : ' ||
                       (DBMS_UTILITY.get_time - l_start)); 

  -- Time the Cached lookup.
  l_start := DBMS_UTILITY.get_time;

  FOR i IN 1 .. l_loops LOOP
    l_debug_on := SYS_CONTEXT(‘global_context’, ‘debug_on’);
  END LOOP;

  DBMS_OUTPUT.put_line('Context Lookup (' || l_loops || ' rows): ' ||
                       (DBMS_UTILITY.get_time - l_start));
END; /

The increased speed of the context approach is evident from the results of this script.

SQL> @global_context_comparison.sql 10
DB Lookup (10 rows)     : 0
Context Lookup (10 rows): 0

PL/SQL procedure successfully completed.

SQL> @global_context_comparison.sql 100
DB Lookup (100 rows)     : 2
Context Lookup (100 rows): 0

PL/SQL procedure successfully completed.

SQL> @global_context_comparison.sql 1000
DB Lookup (1000 rows)     : 19
Context Lookup (1000 rows): 1

PL/SQL procedure successfully completed.

SQL> @global_context_comparison.sql 10000
DB Lookup (10000 rows)     : 190
Context Lookup (10000 rows): 8

PL/SQL procedure successfully completed.

SQL> @global_context_comparison.sql 100000
DB Lookup (100000 rows)     : 1892
Context Lookup (100000 rows): 75

PL/SQL procedure successfully completed.

As with the use of package variables, although a definite performance improvement can be seen, the level to which contexts affects the overall system performance depends on the extent to which you are already using global variables and how you are currently implementing them.

In addition to caching session data, contexts can be used to cache information for the whole instance. Adding the ACCESSED GLOBALLY clause to the end of the context creation statement means the context data is available to all sessions.

CREATE CONTEXT context-name USING package-name ACCESSED GLOBALLY;

This ability makes it possible to use this feature to provide inter-session communication.

 

This is an excerpt from the bestselling book "Oracle PL/SQL Tuning: Expert Secrets for High Performance Programming" by Dr. Tim Hall, Oracle ACE of the year, 2006.

You can buy the book for only $23.95 (30%-off) when you buy directly from the publisher, and you also get instant access to the code depot of PL/SQL tuning scripts:


 

 
��  
 
 
Oracle Training at Sea
 
 
 
 
oracle dba poster
 

 
Follow us on Twitter 
 
Oracle performance tuning software 
 
Oracle Linux poster
 
 
 

 

Burleson is the American Team

Note: This Oracle documentation was created as a support and Oracle training reference for use by our DBA performance tuning consulting professionals.  Feel free to ask questions on our Oracle forum.

Verify experience! Anyone considering using the services of an Oracle support expert should independently investigate their credentials and experience, and not rely on advertisements and self-proclaimed expertise. All legitimate Oracle experts publish their Oracle qualifications.

Errata?  Oracle technology is changing and we strive to update our BC Oracle support information.  If you find an error or have a suggestion for improving our content, we would appreciate your feedback.  Just  e-mail:  

and include the URL for the page.


                    









Burleson Consulting

The Oracle of Database Support

Oracle Performance Tuning

Remote DBA Services


 

Copyright © 1996 -  2017

All rights reserved by Burleson

Oracle ® is the registered trademark of Oracle Corporation.

Remote Emergency Support provided by Conversational