Questions and Answers

Library Cache

?

Library cache latch mapping

2 April 1999

From V$LATCH_CHILDREN, I have uneven contention for just one child library cache latch. Is there a way to track which objects or cursors it points to?
 
? You can take a library cache dump, and examining the trace file. Level 3 is good enough.

alter session set events 'immediate trace name library_cache level 3';

The trace file will contain stuff like this ...

name=SYS.STANDARD
hash=86458413 timestamp=07-04-1994 00:00:00
namespace=TABL/PRCD flags=TIM/SML/[02000000]
kk-dd-aa-ll=00-1d-00-1d lock=0 pin=0 latch=0
You need to look for the 'latch=' string for the child latch your are interested in, and then go back 3 lines to get the object name.
 
 
?

open cursors current

12 April 1999

I have following PL/SQL block:
declare
  cursor c is select empno from emp;
  crs number;
  n number;
begin
  select value into crs from v$mystat where statistic# = 3;
  dbms_output.put_line('curr.op.cursors: ' || crs);
  open c;
  fetch c into n;
  close c;
  select value into crs from v$mystat where statistic# = 3;
  dbms_output.put_line('curr.op.cursors: ' || crs);
end;
The output is as follows:
curr.op.cursors: 2
curr.op.cursors: 4
This means that cursor c remains open. It is closed after the block completes which can be proved by this query:
SQL> select value from v$mystat where statistic# = 3;
    VALUE
---------
        1

Why does the cursor c remain opened after the CLOSE command is submitted?

 
? When you execute an SQL statement, there is a shared SQL area in the SGA, an instantiation in the PGA, and a statement handle in the client environment. Each of these is called a "cursor" in various contexts. Your close call is closing one of the statement handles in your client environment (PL/SQL) but the corresponding instantiation in the PGA remains cached, which is what statistic# 3 is counting. If you were to set close_cached_open_cursors = TRUE and commit after the close call, I think you'll get the result you were expecting.
 
 
?

Hard and soft parses

12 April 1999

It would be helpful if you could give any information on hard vs soft parses and how to get that information from the database.
 
? Version 8 has separate statistics for parse count (total) and parse count (hard). In version 7 the parse count is the total number of parse calls. This is the same as the number of gets against the SQL AREA in V$LIBRARYCACHE. The misses in that view are hard parses. The rest are soft parses.
 
 
?

Library cache lock

16 June 1999

I'm trying to drop a synonym, and it's been waiting on a library cache lock for about an hour now. Is there any way to see who is holding the lock that I'm trying to get? Is there an init.ora parameter I can increase to reduce these problems? This happens frequently.
 
? There is no init.ora parameter that is relevant here. Run $ORACLE_HOME/rdbms/admin/catblock.sql and then use the DBA_KGLLOCK view to see what is happening. This is fairly unusual.
 
 
?

Invalidations

20 August 1999

In V$LIBRARYCAHE for one of my databases, though the miss percentage is very low, reloads are 1329 with invalidations 1116. What are these invalidations? Do I still need to increase the shared pool to reduce the reloads near zero? Could you please throw some light on it?
 
? Shared cursors are marked invalid if the definition of a dependent object is changed. You can see which statements have been affected with:

select sql_text, invalidations from v$sqlarea where invalidations > 0;

To demonstrate, create a test table, select from it, grant and revoke some permissions for it, and you should see the invalidations.

 
 
?

Hash values don't match

27 August 1999

I can join V$SQL to V$OPEN_CURSOR on the ADDRESS column. But if I join it with ADDRESS and HASH_VALUE, I lose most of the entries. Why are the hash values in the two views different when they refer to the same piece of SQL code? I've noticed the same thing happens between V$SESSION and V$SQL.
 
? Guy Harrison hit the same problem a while ago, and here is what he told me: In Oracle 7, the hash values, which are unsigned 32-bit integers internally, were cast to signed values in the X$ tables. This was not really a problem, except that queries could not use the "indexes" on these columns, and attempts to use the hash values in arguments to DBMS_SHARED_POOL.KEEP would fail silently. In Oracle 8.0, Oracle fixed the problem partially, thereby making it much worse. In Oracle8, V$SQL shows the correct hash values, but as you have discovered V$OPEN_CURSOR and V$SESSION do not, so join attempts fail. To work around it, you need to decode the hash value as follows:

decode(sign(HV), -1, HV + power(2,32), HV)

where HV is the hash value column name. This of course suppresses the use of the index on hash value once again, but that leaves you no worse off than you would have been under 7.3!

 
 
?

_kgl_latch_count

8 September 1999

I'd like to know more about _kgl_latch_count . Can you help me in this?
 
? It sets the number of child library cache latches. The default is the least prime number greater than or equal to cpu_count. The maximum is 67. It can safely be increased to combat library cache latch contention, as long as you stick to prime numbers. However it is only effective if the activity across the existing child library cache latches is evenly distributed as shown in V$LATCH_CHILDREN.
 
 
?

Who is doing what?

5 October 1999

Like most folks I have a script which selects from V$SQLAREA and V$SESSION in order to determine who is running a particular SQL statement. The tables are joined by
sql_address = address and
sql_hash_value = hash_value
However if I use an outer join, I see more records, but of course without the session information. Who is executing these? They do not appear to be recursive statements, nor statements being run by a database job. It appears to be user PL/SQL code. Much of it is from Oracle Forms.
 
? Firstly, in release 8.0, the hash value predicate will fail. See the answer from 27 August for an explanation. Secondly, I don't think you can do what you want from the V$ views. However, I written an APT script based on the X$ tables (active_cursors.sql) to do the job.
 
 
?

ORA-600 [17033]

21 October 1999

Just started getting this error:

ORA-00600: internal error code, arguments: [17033], [509], [128], [], [], [], [], []

An entry is being generated every few seconds, and the trace files keep filling up the file system. For now I'm moving them off, but it looks like queries are being affected as well. This happened one other time earlier this summer, and bouncing the database took care of the problem. The only thing I can find on MetaLink is this reference to the _kgl_bucket_count parameter:

Bug 381193 defines a scenario where ORA-600 [17033] is signaled due to lack of resources for the library cache hash table. The workaround for this bug is to set _kgl_bucket_count = 4. Again, this should only be set if it has been determined that the ORA-600 is actually caused by this bug as it can be signaled for other reasons.
Looks like bouncing the database is inevitable. Should I set this parameter as described? Any other suggestions?
 
? First try to flush the shared pool. If that does not work then bounce. If the problem comes back, a change to _kgl_bucket_count will be necessary. Don't just go for 4. Use the APT script kgl_bucket_count.sql to work out the right number for your instance. Of course, the normal caveats about X$ tables and hidden parameters apply. The correct value for this parameter depends on the number of named objects in the library cache, once the library cache has reached its steady state. That is, it is sensitive to the shared pool size, as well as to the application workload. If you change the shared pool size or the workload significantly, then this parameter should be checked.
 
 
?

Library cache hash table expansion

27 October 1999

I understand that the library cache hash table sometimes expands dynamically, and that this can cause a "hiccup" in performance. Is there any X$ structure that I can poll to determine when the hash table is expanding, so that I can try to correlate these events with periodic performance degradation?
 
? I'm not sure what you know about the KGL hash table ...

It starts at 509 buckets by default. If the number of named objects exceeds twice the number of buckets, then a new hash table is allocated at twice the current size, and all objects are rehashed onto the new table before the old hash table is deallocated.

To avoid rehashing, and the simple doubling which leads to a non-prime hash table size, _kgl_bucket_count can be used to set the initial size of the hash table. The parameter is an index into a fixed array, as follows:

0:	509 buckets
1:	1021 buckets
2:	2039 buckets
3:	4093 buckets
4:	8191 buckets
5:	16381 buckets
6:	32749 buckets
7:	65521 buckets
8:	131071 buckets
Our kgl_bucket_count.sql script counts the named objects and divides by 509 as an approximation and then takes the binary log as the index into the bucket count array. This is the value to set _kgl_bucket_count to. It is also coincidentally equal to the number of times that the hash table would have already expanded from its default.

To measure the impact of dynamic rehashing on performance, I would suggest that you capture the output of this script and correlate that with other performance indicators. I expect that you will find that it is heavily dependent on the parse rate. Unfortunately, the higher the parse rate, the greater would be the intrusion effect of running the script regularly.

 
 
?

KQLS heap

30 October 1999

V$SGASTAT shows a lot of memory used by the KQLS heap. What is it? Will it continue to grow or does it eventually flush out?
 
? The KQLS heap is logically part of the dictionary cache, but physically part of the library cache. The amount of memory required is dependent on the complexity of your application schema. You can see which schema objects have the biggest requirements with V$SUBCACHE. Everything in V$SUBCACHE where HEAP_NUM = 10 is the KQLS heap. There is not much that can be done about it, other than avoiding the use of column grants.

In Oracle7 this stuff was in the dictionary cache. However, given that they were "subordinate" caches, only every accessed through their parent, and did not need rowcache enqueue locks to be applied, it was not necessary to have them in the dictionary cache. So they were moved into the library cache in 8.0 as heap number 10 under the library cache handle for the parent object. They are recurrent objects, subject to normal shared pool LRU semantics (rather than those of the dictionary cache). You can get rid of them by flushing, but they will be loaded again if anyone applies a KGL pin to the parent handle. So there is not a lot you can do at a system level. If a lot of memory is required, it is because of the complexity of the schema, and that amount of memory must just be regarded as necessary shared pool overhead. It will not continue to grow, it will reach equilibrium, at a level dependent on the memory pressure in the shared pool.

 
 
?

_kgl_latch_count

20 November 1999

If _kgl_latch_count is set to a higher number than the default, will that help to minimize the latch contention on the library cache latches?
 
? Yes, adjusting _kgl_latch_count is normally effective to reduce library cache latch contention. But stick to prime numbers less than or equal to 67, and no larger than necessary.
 
 
?

cursor_sharing

11 January 2000

We have bad contention for the shared pool latch, and also the library cache latches. We have more than doubled the shared pool size, but it has not helped. Part of the problem seems to be the use of literal SQL. Would you recommend upgrading to 8.1.6 to take advantage of the new cursor_sharing = FORCE feature that automatically converts literals into bind variables?
 
? Latch contention occurs because a latch is held for too long, or because demand for the latch is too high, or both. The normal cause of contention for the shared pool latch is having a shared pool that is too big, and thus long free lists, so that processes hold the latch for a long time. The problem with literal SQL is that a child library cache latch is held for the duration of the parse. Namely, that the latch is held for too long, and too often. Literal SQL does increase the load on both latch types, but the real problem is the duration for which the latches are held.

The 8.1.6 cursor sharing facility will address some problems with the library cache latches, but will not be a panacea for shared pool latch contention. Yes, it may reduce load on the latch somewhat, but you still need to get the shared_pool_size right in order to avoid long free lists and contention under a high execute rate.

 
 
?

shared pool latch again

11 January 2000

Can contention for the shared pool latch be due to the bug that results in long library cache hash chains?
 
? There have been some bugs in this regard in some earlier versions of Oracle. However, from 7.3 onwards the hash value is computed on the entire text of the statement, and the hash table expands dynamically to ensure that the average hash chain length remains below 2. That is, the size of the shared pool has no effect on the length of the library cache hash chains. Also, the length of the library cache hash chains can have no negative impact on contention for the shared pool latch, because the latch levels (5 & 7 respectively) dictate that the shared pool latch is never held while attempting to take a library cache latch. (There is one possible positive impact, namely that contention for the library cache latches may limit contention for the shared pool latch by introducing an earlier bottleneck).
 
 
?

High version count

2 February 2000

We have a problem with an insert statement that suddenly started to run very slowly after about 350,000 inserts. The table is partitioned, and there are several concurrent processes doing the inserts. V$SYSTEM_EVENT shows extensive library cache pin waits, and V$SESSION_WAIT shows that these waits are always on the same library cache handle. The insert statement itself has a very high version count in V$SQLAREA. Flushing the shared pool brings the version count down a little, for a while.
 
? This looks like bug number 315199. In that bug, references to remote objects via a synonym and database link were not recognized as identical. This resulted in spiraling version counts. In that case, the workaround was to use a fully-qualified reference. It may be that a similar bug has been re-introduced. I suggest you contact Oracle support. Also, if you are on version 8.1.5, make sure that you are not using timed_statistics or sql_trace.
 
 
?

Public synonyms

10 February 2000

Is it possible to have too many synonyms? Is it advisable to have private synonyms for individual users, or to have public synonyms? What are the implications of synonym usage on the library cache (and SGA)? This is Oracle 7.3.4, if that matters.
 
? From a performance point of view, public synonyms are one of the worst ideas Oracle ever had, and private synonyms are approximately half as bad. It is better to use fully qualified object references, or use the ALTER SESSION SET CURRENT_SCHEMA command (supported from 8.1). That said, I would rather have 100,000 private synonyms in a database than 100 public synonyms.
 
? Wouldn't that be bad for performance? All those synonyms would hash to the same value in the library cache.
 
? A few more remarks are in order here. The parse phase for a cached shared SQL statement with fully qualified object references only involves establishing the authorization of the user to execute the statement, if that. However, for an equivalent reference via a private synonym, the synonym must be loaded into the library cache, and a dependency structure must be established. For an equivalent reference via a public synonym, the same is done except that it is a "negative dependency" (that is, the cursor is dependent on the non-existence of an object of that name in each user's schema). The statement also has a positive dependency on the public synonym. Each library cache lookup establishes a lock structure, for which memory must be allocated. Each library cache object access establishes a pin structure, which also needs memory. The same goes for loading the metadata for an object not yet present in the library cache, and this commonly involves dictionary cache access and memory management as well.

For a statement that refers to a single table only, the CPU usage during the parse phase is approximately 1:2:4 for a fully-qualified reference, a private synonym and a public synonym respectively. For complex SQL statements, the cost of synonym usage is even greater. The synonym based solutions involve potentially large library cache dependency tables, and are sensitive to the aging out of the library cache objects representing the table name in the users' own schemas. These library cache objects cannot be "kept". In an instance with high parse rates, the use of synonyms increases CPU usage dramatically, and often causes contention on the latches that control access to the library cache, dictionary cache and shared pool.

The suggestion that a large number of private synonyms can cause performance problems in the library cache because they all hash onto the same hash bucket is mistaken. There can only be one user of each name, and the user name is part of the object name on which the hash is calculated. Thus private synonyms do not increase the risk of library cache hash collisions.

People often claim that synonyms are needed to allow code to be tested against differently named schemas, particularly in development. However, as well as the ALTER SESSION SET CURRENT_SCHEMA command, there are numerous code management techniques to obtain the same flexibility without using synonyms. The ALTER SESSION SET CURRENT_SCHEMA command can be issued from an application startup procedure, without any security concerns. However, in versions prior to 8.1, it must be executed before any other SQL is parsed, or there may be risk of data corruption (which is why it was previously unsupported).

 
 
?

8.1.5 performance

6 March 2000

We are trying to move up from Oracle 7.3.4 to Oracle 8.1.5. But the performance is unacceptable. Are there any known issues?
 
? The big issue is that you must not use timed_statistics or sql_trace against 8.1.5.0. If you do, cursor's will not be shared, and the VERSION_COUNTs in V$SQLAREA will be very high. This causes lots of CPU time to be wasted traversing the tables of child library cache objects, and probably library cache latch contention as well. This bug (918002) is fixed in 8.1.5.1, but there is still a similar bug (1210242) with sql_trace not fixed until 8.1.6.2.

There have also been dramatic changes in the management of Oracle's buffer cache in release 8.1. In general, these are good for performance and result in higher cache hit rates. However, some cache-intensive "bad" SQL does worse under the new algorithms. The queries affected are those that use a small enough set of blocks to fit in cache, but larger than can remain concurrently pinned, and then use those blocks repeatedly and intensively.

 
 
?

Performance using roles

6 March 2000

Are there any performance issues regarding the use of roles? According to Oracle it is a good practice to have roles at various levels. For example, for each sub-system one would have:
SUB_SYSTEM_SEL_ROLE
SUB_SYSTEM_INS_ROLE
SUB_SYSTEM_UPD_ROLE
SUB_SYSTEM_DEL_ROLE
SUB_SYSTEM_ALL_ROLE
These roles would then be assigned to a set of user roles according the sub-systems and access levels required by each group of users. My concern is that there might be an overhead for Oracle to resolve this nesting of roles while parsing?
 
? From a performance point of view, having a hierarchy of roles is OK. The list of enabled roles is cached in the UGA (visible via X$KZSRO) and when scanning the list of grants for an object during cursor authorization, no further work is needed to determine whether the user has a particular role and whether it is enabled. The cost of maintaining the list of enabled roles is borne at session startup, and when the SET ROLE command is issued, not during cursor authorization.

There is however a clear case for reducing the number of grants against each object (by using roles). The grants live in the KQLS heap, which is logically part of the dictionary cache, but physically part of heap 10 of the library cache object. Large numbers of grants increase the size of heap 10, and the CPU required to scan it, so roles may be useful to reduce these costs. The way cursor authorization works is that the library cache object for a cursor contains an accesses table which enumerates the privileges required on all the objects accessed by the cursor. For a user to be authorized to execute the cursor, the user must have the required permission on each accessed object. For each access, the library cache object is pinned, and the grants are scanned linearly for a match against their enabled roles. The authorization is then cached in the library cache object for the cursor, so that subsequent executions of that cursor by the same user do not require re-authorization.

 
 
?

V$OPEN_CURSOR

8 March 2000

V$OPEN_CURSOR does not seem to show all the open cursors. I have an application that has 19 open cursors, but only 10 of them are visible in V$OPEN_CURSOR.
 
? V$OPEN_CURSOR actually shows you the SGA structures that the documentation calls "breakable parse locks". The UGA can retain cursor instantiations for which the parse lock has been broken (however a reload would be needed prior to re-execution). The UGA can also retain instantiations (and thus parse locks for some time) for cursors that the client has explicitly closed, subject to the session_cached_cursors limit. Thus there is no necessary relationship between the number of cursors that the client program thinks it has open, and the number shown by V$OPEN_CURSOR.
 
 
?

shared pool latch contention

16 March 2000

One of the reasons that shared pool latch contention can become so severe where applications fail to properly use bind variables appears to be the length of the lists of free memory chunks which must be scanned when making space for the new object in the shared pool. As these free lists are organized by size categories, it occurs to me that perhaps the problem could be mitigated if the new objects could be pseudo-randomly coerced into different size categories to balance the load. This could be accomplished by injecting strategically sized comments into the SQL before sending it to Oracle. Am I completely off my rocker on this?

Of course Oracle is claiming to remedy this with the new cursor_sharing initialization parameter in 8.1.6. Have you tried this out yet?

 
? The use or otherwise of bind variables is logically a different problem to that of shared pool free space fragmentation. The 8.1.6 cursor_sharing parameter is doing a wonderful job for one of my clients whose application does not use bind variables. It is still important however to get the shared pool size right to prevent fragmentation.

I believe that 8.2 will address this problem by rounding up all memory allocations to one of a set of fixed sizes. This may waste a lot of shared pool memory, but will kill the fragmentation issue entirely. Controlling (or randomizing) the sizes of SQL statements is not feasible at present, because most of the chucks that affect the problem presently are not actually from the SQL area.

 
? I thought that not using bind variables would have a relationship to shared pool fragmentation in that since each statement is new, the heap manager would be called upon much more frequently than otherwise.
 
? Yes, it certainly increases the work, but if the pool is small then the fragmentation does not get too severe. I suppose it would be best to say that they are interrelated, although logically distinct issues.
 
 
?

Dictionary cache miss rate

24 March 2000

Using Statspack on an Oracle 8.1.5 database, I noticed a high dictionary cache miss rate. I have done some tuning, but still have high percentage misses. The suggestion (as per the Statspack report) is that the miss rate should be less than 2%. Any ideas on what the problem could be?
 
? The Statspack advice is unrealistic. Oracle often has to check for the non-existence of things in the dictionary cache, and these gets invariably result in misses. One example of this is when referencing an object through a public synonym. Oracle has to do a get against the dc_objects rowcache for an object of the same name in the current schema. That get of course results in a miss.
 
 
Copyright © Ixora Pty Ltd Send Email Home