Oracle problems
gc buffer busy acquire / release: The Hot Block, and the Fix
3 November 2026
gc buffer busy acquire and gc buffer busy release are the RAC form of a hot block: the buffer this session needs is in the middle of a Cache Fusion transfer, because another session on this instance has already asked another instance for it, or because another instance has just taken it away. Nothing is lost and the network may be fine; the block is wanted by too many sessions on too many instances at once, and Oracle queues them. The queries below name the block and its segment, say whether the transfers behind the queue are delayed by contention or by load, and rank the statements that pay for it. The fix is in where the work runs, in the sequence that feeds the index, and, for the congested case, in the CPUs and the GCS server processes of the node that serves the blocks.
What the two events mean
Oracle's reference describes gc buffer busy acquire as the wait of a session whose "requested buffer was globally busy in the cluster, because it had already been requested from a remote instance by another local client", and gc buffer busy release as the same wait when the buffer "had been transferred away by a remote instance and needed to be requested again". The wait time of both is "the actual time it took to resolve the buffer contention", and the parameters are file#, block# and class#, the same three as buffer busy waits on a single instance. The RAC guide says what the contention is: "a gc buffer busy event indicates that Oracle Database cannot immediately grant access to data that is stored in the local buffer cache. This is because a global operation on the buffer is pending and the operation has not yet completed", and "The existence of gc buffer busy events also means that there is block contention that is resulting in multiple requests for access to the local block. Oracle Database must queue these requests." The queue is as long as the transfer behind it is slow, which is why the busy waits of one block and the transfer times of the whole cluster are read together.
The block, right now
SELECT inst_id, event, p1 AS file#, p2 AS block#, p3 AS class#,
sql_id, COUNT(*) AS sessions
FROM gv$session
WHERE event IN ('gc buffer busy acquire', 'gc buffer busy release')
AND state = 'WAITING'
GROUP BY inst_id, event, p1, p2, p3, sql_id
ORDER BY sessions DESC;
One file and block with fifteen sessions behind it on two instances is the hot block, and one statement behind all of them is the statement to read. The segment that owns the block:
SELECT owner, segment_name, segment_type, partition_name
FROM dba_extents
WHERE file_id = :file#
AND :block# BETWEEN block_id AND block_id + blocks - 1;
The class says what kind of block it is, and V$WAITSTAT names the classes: a data block of an index fed by a sequence, a data block of a small table that every instance updates, a segment header handing out space, or an undo header. As with the single-instance wait, the fix depends on the class.
The segments the cluster fights over
The RAC guide: "An additional segment statistic, gc buffer busy, has been added to quickly determine the busy objects without having to query the V$SESSION_WAIT view mentioned earlier." With the two received counters beside it, the list is the working set the instances share:
SELECT inst_id, owner, object_name, object_type,
statistic_name, value
FROM gv$segment_statistics
WHERE statistic_name IN ('gc buffer busy', 'gc cr blocks received',
'gc current blocks received')
AND value > 0
ORDER BY value DESC
FETCH FIRST 20 ROWS ONLY;
The counters run since instance start, so two readings an hour apart give the hour. An index at the top of all three lists on every instance is the sequence-fed index; a small table at the top of gc current blocks received is the one every instance updates; and the guide puts the cause of most of it in one sentence: "Usually, either interconnect or load issues or SQL execution against a large shared working set can be found to be the root cause."
Busy or congested: why the transfer was slow
A buffer stays busy for as long as the transfer behind it takes, and V$INSTANCE_CACHE_TRANSFER splits every block received by this instance by what delayed it. Oracle's reference defines the columns: CR_BUSY is "CR Block transfers affected by remote contention", CR_CONGESTED is "CR Block transfers affected by remote system load", CURRENT_BUSY and CURRENT_CONGESTED are the same for current blocks, and LOST is "The number of blocks that were sent by a particular instance but that never arrived in this instance":
SELECT inst_id, instance AS from_inst, class,
cr_block, cr_busy, cr_congested,
current_block, current_busy, current_congested, lost
FROM gv$instance_cache_transfer
WHERE cr_block + current_block > 0
ORDER BY cr_busy + cr_congested
+ current_busy + current_congested DESC;
The time columns say the same per cause: CR_BUSY_TIME is the time of CR blocks "delayed by a log flushed on the sending instance", and CR_CONGESTED_TIME the time of CR blocks "delayed because LMS was busy". That is the diagnosis in two words. Busy is contention on the other node: the guide says of gc current block busy and gc cr block busy that "the sending of the block was delayed on a remote instance. For example, a block cannot be shipped immediately if Oracle Database has not yet written the redo for the block's changes to a log file", so a slow log writer on one node makes every busy block slower on the other. Congested is load: the LMS processes that serve the blocks are behind, and the reference says of the congested waits that increasing the GCS server processes "is usually the remedy". Lost is the network, and has its own page. The same split, system-wide, as wait events:
SELECT inst_id, event, total_waits,
ROUND(time_waited_micro/NULLIF(total_waits,0)/1000,2) AS avg_ms
FROM gv$system_event
WHERE event IN ('gc buffer busy acquire', 'gc buffer busy release',
'gc cr block busy', 'gc current block busy',
'gc cr block congested', 'gc current block congested',
'gc cr block 2-way', 'gc current block 2-way',
'gc cr block 3-way', 'gc current block 3-way')
ORDER BY inst_id, time_waited_micro DESC;
The 2-way and 3-way waits are the normal transfers; Oracle's reference says "The Cache Fusion protocol guarantees that requests are fulfilled in 3 hops or less", and their average is the speed of the interconnect, where the sign of trouble is a change against the usual, not a value. The busy and congested averages above it are the delay. The guide's warning applies to all the totals: "Most global cache wait events that show a high total time as reported in the AWR and Statspack reports or in the dynamic performance views are normal and may present themselves as the top database time consumers without actually indicating a problem."
The statements that pay for it
Every cursor keeps its own cluster wait time, and the RAC guide names the column, CLUSTER_WAIT_TIME in V$SQLAREA:
SELECT sql_id, executions,
ROUND(cluster_wait_time/1e6, 1) AS cluster_s,
ROUND(elapsed_time/1e6, 1) AS elapsed_s,
SUBSTR(sql_text, 1, 60) AS sql_text
FROM v$sqlarea
WHERE cluster_wait_time > 0
ORDER BY cluster_wait_time DESC
FETCH FIRST 10 ROWS ONLY;
A statement whose cluster time is most of its elapsed time, run from every instance against the segments at the top of the list above, is the shared working set, and it is usually one or two statements rather than the whole application.
The GCS server processes
SELECT inst_id, name, value, isdefault
FROM gv$parameter
WHERE name = 'gcs_server_processes';
Oracle's reference: "GCS_SERVER_PROCESSES specifies the number of background GCS server processes (LMSn and LMnn) to serve the inter-instance traffic among Oracle RAC instances." The default is computed from the hardware, in the reference's order: 1 for 1 to 3 CPUs, 2 for 4 to 15, the CPUs divided by 6 at 128 or more CPUs with an SGA of 100 GB or more, and otherwise 2 plus the CPUs divided by 32, fractions dropped, so a node with 20 CPUs gets 2. The parameter is not modifiable while the instance runs, so it is set with SCOPE = SPFILE and takes effect at the next start, and its range on a RAC database is 1 to 100. The sentence that matters for the congested case is the reference's own: "If there is high Cache Fusion congestion on the system, the number of GCS server processes could be increased to reduce Cluster wait time."
The fix, in order
- Read the busy, congested and lost columns before you change anything. Busy with lost at zero is contention, and the fix is in the application and the schema. Congested is load on the node that serves the blocks. Lost is the network, and nothing on this page fixes it.
- Give each hot object one instance. The guide's root cause is "SQL execution against a large shared working set", and the working set stops being shared when the application that works on those tables runs on one node: a service with one preferred instance for the batch and another for the users, so the blocks stay in one cache and cross the interconnect only when the other node really needs them. This is the fix that removes the waits instead of speeding them up.
- A sequence-fed index: spread the inserts. Every instance inserting into the same rightmost leaf block is the classic RAC hot block. A scalable sequence,
CREATE SEQUENCE ... SCALE, affixes a numeric offset to the beginning of each value, in the words of Oracle's reference, so inserts from different instances and sessions land in different leaf blocks; a hash-partitioned index does the same for an existing key; a reverse key index spreads them too but costs every range scan on that column. Give the sequence itself a largeCACHEandNOORDER, so the instances do not also queue on the sequence. - A small table every instance updates: fewer rows per block, or one instance. A higher
PCTFREEputs fewer hot rows in each block; a counter row that every transaction updates is an application design that a sequence or a row per session replaces; and a lookup table that both nodes update at once is better updated from one of them. - Segment headers and free space: ASSM and partitions. A segment header in the busy list is sessions on several instances asking one block for space; automatic segment space management spreads them across bitmap blocks, and a hash-partitioned table gives each instance's inserts a segment of its own.
- Congested: give the LMS processes air. The guide says the load-related waits are "usually caused by high load, CPU saturation and would have to be solved by additional CPUs, load-balancing, off loading processing to different times or a new cluster node". A saturated node delays every block it serves, for every other node. When the CPUs have room and the transfers are still congested, raise
GCS_SERVER_PROCESSESat the next restart. - Do not tune the normal numbers. A cluster that shares blocks has global cache waits, and the guide says most of them are normal even at the top of the report. The number to act on is the one that is higher than the same hour last week, which is the comparison Radar Engine makes.
See it coming
Radar Engine, the detection layer of Scops, samples every session on every instance every 5 seconds, knows the usual size of the Cluster wait class at each hour, and watches the transfer times and the lost-block counters of every RAC database, so the hot block of a new release is a finding with the block, the segment and the statement while the queue is still ten sessions long:
| Detector | Clock | When it fires |
|---|---|---|
| Cluster waits surging | Live. Twice the hour before, well above its usual spread. | Watch. With a second sign, such as 5 blocked sessions or commits three times slower: Warning. Above max(4, 4 × usual) active sessions, with an effect: Critical. |
| Waits on gc buffer busy acquire | Live. A sudden large share of the waits. | Watch. The largest one, if it continues: Warning. |
| RAC interconnect trouble | Live, RAC only. Lost blocks, or transfer times three times the usual, for 10 minutes. | Warning. Both: Critical. |
| Unusual Cluster waits | Hourly, against the same hour on other days. | By size, duration and cause: the usual load, many statements, a backup or a database link. Critical only with a named cause, high for 3 hours. |
The finding names the database, the instances, the event, the statement behind most of the waiting sessions and the segment they meet on, and the Activity chart draws the Cluster class by instance, statement and object, with nothing installed on the cluster and no Diagnostics Pack.
Questions
What does gc buffer busy acquire mean?
A session on a RAC instance needs a buffer that another session on the same instance has already requested from another instance, so it waits for that transfer to finish. Oracle's reference calls the buffer "globally busy in the cluster"; the wait is contention on a hot block, not a lost or slow network packet.
What is the difference between gc buffer busy acquire and gc buffer busy release?
Acquire: another local session asked a remote instance for the buffer first, and this session waits behind it. Release: a remote instance has just taken the buffer away, and this instance has to request it again. Both carry the file, block and class in P1, P2 and P3.
What is the difference between gc buffer busy and gc cr block busy?
gc buffer busy is the queue on this instance for a block that is in transit. gc cr block busy and gc current block busy are the transfer itself, delayed on the sending instance, for example because its redo had not yet been written to a log file. V$INSTANCE_CACHE_TRANSFER counts those delayed transfers in its busy columns, and the congested columns count the ones delayed by load on the sending node.
How do I find the object behind gc buffer busy waits?
V$SESSION gives the file and block in P1 and P2 for the waiting sessions, DBA_EXTENTS names the segment that owns the block, and V$SEGMENT_STATISTICS ranks the segments by the gc buffer busy statistic since startup, which Oracle added so that the busy objects can be found without catching the sessions in the act.
Should I raise GCS_SERVER_PROCESSES?
Only for congested transfers, which V$INSTANCE_CACHE_TRANSFER counts separately from busy ones. Oracle's reference says the number of GCS server processes could be increased to reduce Cluster wait time when there is high Cache Fusion congestion; it is set in the spfile and takes effect at the next restart. Busy transfers are fixed in the application and the schema.
Related problems
- RAC lost blocks: gc cr block lost
- buffer busy waits
- Log file sync waits
- CPU at 100%
- One SQL taking the whole database
- Oracle wait events, by class
- All Oracle problems