Monday 30 July 2012

DB BUFFER CACHE


Latches are internal memory structures that coordinate access to shared resources. Locks (also known as enqueues) are different from latches, the key difference being that enqueues, as the name suggests, provide a FIFO queueing mechanism, while latches do not. On the other hand, latches are held very briefly and locks are usually held longer.

In Oracle SGA, the buffer cache is the memory area into which data blocks are read. (If Automatic Shared Memory Management [ASMM] is in use, part of the shared pool can be tagged as KGH:NO ALLOC and remapped to the buffer cache area too.)

Each buffer in the buffer cache has an associated element in the buffer header array, externalized as x$bh. Buffer headers keep track of various attributes and state of buffers in the buffer cache. This buffer header array is allocated in the shared pool. The buffer headers are chained together in a doubly-linked list and linked to a hash bucket. There are many hash buckets, and their number is derived and governed by the _db_block_hash_buckets parameter). Access to these hash chains (both to inspect and change) is protected by cache-buffers-chains latches.

Furthermore, buffer headers can be linked and delinked from hash buckets dynamically.

Here is a simple algorithm to access a buffer (I had to deliberately cut out so as not to deviate too much from our primary discussion):


1. Hash the data block address (DBAs: a combination of tablespace, file_id and block_id) to find hash bucket.
2. Get the latch protecting the hash bucket.
3. If success, 
walk the hash chain (hash bucket), 
reading buffer headers (shared pool) to see if a specific version of the block is already in the chain.
    If found, access the buffer in buffer cache, with protection of buffer pin/unpin actions.





If not found, 
then find a free buffer in buffer cache, 
unlink the buffer header for that buffer from its current chain, 
link that buffer header with this hash chain, 
release the latch and read block in to that free buffer in buffer cache with buffer header pinned.







4. If not success, spin for spin_count times and go to step 2. If that latch was not got with spinning, then sleep (with exponentially increasing sleep time with an upper bound), wakeup, and go to step 2.

Obviously, latches are playing crucial role in controlling access to critical resources such as the hash chain. My point is that repeated access to a few buffers can increase latch activity.

There are many CBC latch children. The parameter _db_block_hash_latches controls the number of latches and is derived from the buffer cache size. Furthermore, in Oracle 10g, shareable latches are used; and inspecting a hash chain necessitates acquiring latches in shared mode, which is compatible with other shared-mode operations. Note that these undocumented parameters are usually sufficient, and changes to these parameters must get approval from Oracle support.


No comments: