Oracle V$LATCH Performance Guide - Latch Contention Analysis
Oracle V$LATCH Performance Guide
Section titled “Oracle V$LATCH Performance Guide”Understanding and resolving Oracle latch contention for optimal database performance.
What Are Latches?
Section titled “What Are Latches?”Latches are low-level serialization mechanisms that protect shared memory structures. Unlike locks, latches are:
- Held for very short periods (microseconds)
- Not queued (requesters spin or sleep)
- Used to protect SGA memory structures
Key Latch Views
Section titled “Key Latch Views”V$LATCH - System-Wide Statistics
Section titled “V$LATCH - System-Wide Statistics”-- Top latches by sleeps (contention)SELECT NAME, GETS, MISSES, SLEEPS, SPIN_GETS, ROUND(MISSES/NULLIF(GETS, 0) * 100, 2) AS miss_ratioFROM V$LATCHWHERE GETS > 0ORDER BY SLEEPS DESCFETCH FIRST 10 ROWS ONLY;V$LATCH_CHILDREN - Child Latches
Section titled “V$LATCH_CHILDREN - Child Latches”-- Hot child latchesSELECT NAME, CHILD#, GETS, MISSES, SLEEPS, IMMEDIATE_GETS, IMMEDIATE_MISSESFROM V$LATCH_CHILDRENWHERE SLEEPS > 0ORDER BY SLEEPS DESCFETCH FIRST 20 ROWS ONLY;V$LATCHHOLDER - Current Holders
Section titled “V$LATCHHOLDER - Current Holders”-- Who's holding latches nowSELECT lh.PID, lh.SID, lh.LADDR, lh.NAME, s.USERNAME, s.PROGRAMFROM V$LATCHHOLDER lhJOIN V$SESSION s ON lh.SID = s.SID;Common Latch Types
Section titled “Common Latch Types”| Latch Name | Related To | Common Cause |
|---|---|---|
| cache buffers chains | Buffer cache | Hot blocks, poor SQL |
| shared pool | Shared pool | Hard parsing, small pool |
| library cache | Cursor sharing | Hard parsing, invalidations |
| redo allocation | Redo generation | High redo volume |
| redo copy | Redo copying | High redo volume |
| row cache objects | Dictionary cache | Excessive DDL |
| simulator lru latch | DB cache | Buffer cache sizing |
Cache Buffers Chains Latch
Section titled “Cache Buffers Chains Latch”Most common latch contention issue.
Diagnose
Section titled “Diagnose”-- Find hot blocks causing contentionSELECT e.OWNER, e.OBJECT_NAME, e.OBJECT_TYPE, ash.CURRENT_FILE#, ash.CURRENT_BLOCK#, COUNT(*) AS waitsFROM V$ACTIVE_SESSION_HISTORY ashJOIN DBA_EXTENTS e ON ash.CURRENT_FILE# = e.FILE_ID AND ash.CURRENT_BLOCK# BETWEEN e.BLOCK_ID AND e.BLOCK_ID + e.BLOCKS - 1WHERE ash.EVENT LIKE 'latch: cache buffers chains%' AND ash.SAMPLE_TIME > SYSDATE - 1/24GROUP BY e.OWNER, e.OBJECT_NAME, e.OBJECT_TYPE, ash.CURRENT_FILE#, ash.CURRENT_BLOCK#ORDER BY COUNT(*) DESCFETCH FIRST 10 ROWS ONLY;Resolution
Section titled “Resolution”-- Option 1: Reduce logical I/O in SQL-- Tune queries hitting hot blocks
-- Option 2: Partition hot tables-- Spreads access across multiple blocks
-- Option 3: Use hash clusters for extreme cases-- Distributes rows by hash value
-- Option 4: Increase _db_block_hash_buckets (hidden parameter)-- Consult Oracle Support firstShared Pool Latch
Section titled “Shared Pool Latch”Diagnose
Section titled “Diagnose”-- Check shared pool fragmentationSELECT POOL, NAME, BYTES/1024/1024 AS mb, REQUEST_FAILURESFROM V$SGASTATWHERE POOL = 'shared pool'ORDER BY BYTES DESC;
-- Check for hard parsingSELECT PARSE_CALLS, EXECUTIONS, PARSE_CALLS/NULLIF(EXECUTIONS, 0) AS parse_per_execFROM V$SQLAREAWHERE PARSE_CALLS > EXECUTIONSORDER BY PARSE_CALLS DESCFETCH FIRST 10 ROWS ONLY;Resolution
Section titled “Resolution”-- Increase shared poolALTER SYSTEM SET SHARED_POOL_SIZE = 2G SCOPE=BOTH;
-- Enable cursor sharing (if appropriate)ALTER SYSTEM SET CURSOR_SHARING = FORCE;
-- Keep large objects pinnedEXEC DBMS_SHARED_POOL.KEEP('schema.package', 'P');Library Cache Latch
Section titled “Library Cache Latch”Diagnose
Section titled “Diagnose”-- Check library cache efficiencySELECT NAMESPACE, GETS, GETHITRATIO, PINS, PINHITRATIO, RELOADS, INVALIDATIONSFROM V$LIBRARYCACHE;
-- Find SQL with high version countSELECT SQL_ID, VERSION_COUNT, EXECUTIONS, SQL_TEXTFROM V$SQLAREAWHERE VERSION_COUNT > 10ORDER BY VERSION_COUNT DESCFETCH FIRST 10 ROWS ONLY;Resolution
Section titled “Resolution”-- Use bind variables-- Instead of: SELECT * FROM emp WHERE id = 100-- Use: SELECT * FROM emp WHERE id = :1
-- Reduce cursor invalidations-- Avoid DDL on tables with active DML
-- Pin frequently used objectsEXEC DBMS_SHARED_POOL.KEEP('SYS.DBMS_OUTPUT', 'P');Redo Latches
Section titled “Redo Latches”Diagnose
Section titled “Diagnose”-- Redo latch contentionSELECT NAME, GETS, MISSES, SLEEPSFROM V$LATCHWHERE NAME IN ('redo allocation', 'redo copy', 'redo writing');
-- Redo generation rateSELECT * FROM V$SYSSTAT WHERE NAME LIKE 'redo%';Resolution
Section titled “Resolution”-- Increase log buffer (if redo allocation contention)ALTER SYSTEM SET LOG_BUFFER = 128M SCOPE=SPFILE;
-- Use private redo strands (automatic in 10g+)-- Check _log_parallelism_dynamic
-- Reduce redo generation-- Use NOLOGGING for bulk operations where appropriateMutex vs Latch (10g+)
Section titled “Mutex vs Latch (10g+)”Oracle replaced some latches with mutexes for better scalability.
-- Check mutex waitsSELECT MUTEX_TYPE, LOCATION, SLEEPS, WAIT_TIMEFROM V$MUTEX_SLEEPORDER BY SLEEPS DESCFETCH FIRST 10 ROWS ONLY;
-- Cursor mutex contentionSELECT MUTEX_TYPE, GETS, SLEEPSFROM V$MUTEX_SLEEP_HISTORYWHERE MUTEX_TYPE LIKE 'Cursor%'ORDER BY SLEEPS DESC;Latch Performance Metrics
Section titled “Latch Performance Metrics”Miss Ratio
Section titled “Miss Ratio”-- Target: < 1% miss ratioSELECT NAME, GETS, MISSES, ROUND(MISSES/NULLIF(GETS, 0) * 100, 4) AS miss_pctFROM V$LATCHWHERE GETS > 1000ORDER BY miss_pct DESC;Sleep Ratio
Section titled “Sleep Ratio”-- Sleeps indicate serious contentionSELECT NAME, MISSES, SLEEPS, ROUND(SLEEPS/NULLIF(MISSES, 0) * 100, 2) AS sleep_pctFROM V$LATCHWHERE MISSES > 0ORDER BY SLEEPS DESC;Willing-to-Wait vs Immediate
Section titled “Willing-to-Wait vs Immediate”-- Compare wait modesSELECT NAME, GETS AS willing_to_wait, IMMEDIATE_GETS AS no_wait, MISSES, IMMEDIATE_MISSESFROM V$LATCHWHERE GETS > 0 OR IMMEDIATE_GETS > 0ORDER BY GETS DESCFETCH FIRST 10 ROWS ONLY;Latch Wait Events
Section titled “Latch Wait Events”-- Current latch waitsSELECT SID, EVENT, P1TEXT, P1, P2TEXT, P2, SECONDS_IN_WAITFROM V$SESSIONWHERE EVENT LIKE 'latch%'AND STATE = 'WAITING';
-- Historical latch waitsSELECT EVENT, COUNT(*) AS samples, ROUND(COUNT(*) * 100 / SUM(COUNT(*)) OVER(), 2) AS pctFROM V$ACTIVE_SESSION_HISTORYWHERE EVENT LIKE 'latch%' AND SAMPLE_TIME > SYSDATE - 1GROUP BY EVENTORDER BY COUNT(*) DESC;Key Metrics Summary
Section titled “Key Metrics Summary”| Metric | Good | Warning | Critical |
|---|---|---|---|
| Miss Ratio | < 0.5% | 0.5-1% | > 1% |
| Sleep Ratio | < 1% | 1-5% | > 5% |
| Spin Gets/Misses | > 90% | 80-90% | < 80% |