当进程想要获取锁存器而此时该锁存器正被其他进程持有时产生Latch Free(锁存器空闲)等
待事件,类似于排队,Oracle使用锁存器来保护数据结构。一次只能在一个进程在获得锁存器后
修改或检查数据结构。其他需要访问该数据结构的进程必须等到它们获得锁存器后。不同于排队
的是,请求锁存器的进程不需要在队列中等待。如果获取锁存器失败,则进程仅仅等待一小段时
间就可以再次请求锁存器。这一小段等待时间成为“自旋”(spin)。如果在一次或多次自旋重复
(spin iterations)之后还没获取锁存器,进程就休眠一小段时间,然后再次尝试获取锁存器,
接下来休眠更长一段时间,直到获得锁存器。
最常见的锁存器有:cache buffer chains(高速缓存缓冲区链)、library cache(高速缓存)
和shared pool(共享池)。
1、等待参数
latch free的等待参数描述如下:
◎ P1 进程等待的锁存器地址。
◎ P2 锁存器号,同v$latchname.latch#
要查找等待锁存器的名称,可以是哟功能如下SQL语句:
SELECT *
FROM v$latchname
WHERE latch# = &
2_Value;
◎ P3 尝试的次数;显示进程试图获取锁存器的次数计数器。
2、等待时间
该时间的等待时间呈指数级增长。他不包含进程为锁存器自旋(spin) 花费的时间。
以不等待模式获取的锁存器在IMMEDIATE_GETS和IMMEDIATE_MISSES列中统计。
通过愿意等待模式获取锁存器在GETS和MISSES列中有统计。特殊锁存器的GETS列在每次进程
通过愿意等待模式请求该锁存器时递增。
如果锁存器不能用,那么进程会在CPU上自旋(spin)一小段时间,重新尝试该锁存器。
v$system_Event视图中的latch free等待事件的total_waits统计追踪进程以愿意等待模式
无法获得一个锁存器的次数。v$latch视图中特殊锁存器的sleeps统计追踪进程在锁存器上睡眠
的次数。因为进程在_SPIN_COUNT次数后无法获得锁存器时没有别的事可做只好睡眠,total_times
应该等于sleeps的综合,然而,很多时候total_times大于sleeps的总合。这是因为sleeps统计
只有在锁存器GET操作成功才更新,而不是每次尝试是更新。
因为latch free等待事件总是很短,所以可以看到total_waits的一个较大的数字,这是计
数器在一段短时间内发生的等待事件。
3、常见原因、诊断和动作
锁存器征用表名另一个进程持有该锁存器过长的时间。当结合高需求量,这种争用带
来的影响将会扩大,从而明显地降低性能。锁存器争用在高度并发的环境中很普遍。可以
根据如下SQL查看进程竞争的热锁存器:
SELECT NAME,
Gets,
Misses,
Immediate_Gets,
Immediate_Misses,
Sleeps
FROM V$latch
ORDER BY Sleeps;
◎ shared pool锁存器和library cache锁存器的争用——解析
shared pool锁存器和library cache锁存器的争用主要是由于紧密的硬解析。过多
的硬解析通常出现在主要使用带有字面值的SQL语句的应用程序中。应解析是代价
昂贵的才做,并且在解析期间必须持有子library cache锁存器。
①.使用下面语句查数据库中硬解析的数量:
SELECT a.*,
SYSDATE - b.Startup_Time Days_Old
FROM V$sysstat a,
V$instance b
WHERE a.NAME LIKE 'parse%';
②.发现执行许多硬解析的当前会话:
SELECT a.Sid,
c.Username,
b.NAME,
a.VALUE,
Round((SYSDATE - c.Logon_Time) * 24) Hours_Connected
FROM V$sesstat a,
V$statname b,
V$session c
WHERE c.Sid = a.Sid
AND a.Statistic# = b.Statistic#
AND a.VALUE > 0
AND b.NAME = 'parse count (hard)'
ORDER BY a.VALUE;
③.标识作为绑定变量的合适候选的literal SQL语句:
SELECT Hash_Value,
Substr(Sql_Text, 1, 80)
FROM V$sqlarea
WHERE Substr(Sql_Text, 1, 40) IN
(SELECT Substr(Sql_Text, 1, 40)
FROM V$sqlarea
HAVING COUNT(*) > 4
GROUP BY Substr(Sql_Text, 1, 40))
ORDER BY Sql_Text;
④.正确的设置SESSION_CACHED_CURSOES参数:
每当SQL语句到达时,Oracle检查该语句是否已经在库高速缓存中。如果是的话,
只需要很少的开销就可以执行该语句;这种进程被称为软解析。在硬解吸不行时,软
解析也不好。library cache锁存器在软解析中获得。Oracle仍然必须检查语句的语法
和语义,除非该语句高速缓存在会话的游标高速缓存中。通过正确的设置
SESSION_CACHED_CURSOES参数,可以减少library cache锁存器持有时间。然而最好的
方法是减少软解析的数量,这只可通过应用程序完成。
通过在v$sqlarea视图中查找带有大量parse_calls的语句,你可以找到令人不
愉快的语句。
如果发现数据库具有长共享池空闲列表,并且应用程序使用literal SQL,那么就
应该考虑减少SHARED_POOL_SIZE。这将减少share pool锁存器的争用。
也应该使用dbms_shared_pool.keep过程钉住共享池中可重用的对象。
v$db_object_cache视图具有保存相关对象的信息。
◎ library cache锁存器的争用——带有高版本数的语句
Oracle使用多个子游标来区分一些SQL语句,这些SQL语句具有相同的字符,但是不能
被共享,因为他们引用不同的底层对象。例如:如果数据库有三个Customer表,并且
每个表属于不同的模式,那么每个拥有者发布的SELECT * FROM Customer语句将具有
相同的散列值,但是具有不同的子段数量。当被解析语句散列值匹配带有高的子段数
或版本数的语句散列值时,Oracle必须比较语句和所有的现有版本。必须在检查期间
持续持有library cache锁存器,着可能造成其他进程无法实现他们的library cache
锁存器请求。通过在数据库中使用唯一的对象名,可以最小化这个问题。
查询列出v$sqlarea中版本数大于20的所有SQL语句:
SELECT Version_Count,
Sql_Text
FROM V$sqlarea
WHERE Version_Count > 20
ORDER BY Version_Count,
Hash_Value;
◎ cache buffer chains锁存器
在将数据读入SGA时,他们的缓冲区头被防止在悬挂散列存储桶的链表中(散列链)。
这种内存结构由大量子cache buffers chains锁存器(也称散列锁存器或CBC锁存器)
保护。希望在添加、删除、搜索、检查、读取、或修改块的进程必须首先获得cache
buffers chains锁存器,从而保护链上的缓冲区。这样就可以保证独占访问,并防
止其它进程接下来读取或改变同一个链。为了完整性牺牲了并发性。通过设置
_DB_BLOCK_HASH_LATCHS参数可以调整散列锁存器数量。
如下SQL取实例中散列锁存器的数量:
SELECT COUNT(DISTINCT(Hladdr)) FROM X$bh;
①.cache buffers chains锁存器的争用——底效率的SQL语句
低效率的SQL语句是cache buffers chains锁存器争用的主要原因。当和高并发
率混合在一起时,花费在latch free等待事件上的时间可能更多。在某些环境中,
应用程序打开执行相同的低效率SQL语句的多个并发会话,并且这些SQL语句都没法得
到相同的数据集,这种情况下相当普遍。
如果集注下面3个方面,你可以做的很好:
◆ 每个逻辑读取需要一个latch gey操作和一个CPU
◆ 从latch get例程中获得的唯一方法是获得锁存器
◆ 在任意时刻,只有一个进程可以拥有cache buffer链,并且这个锁存器覆盖
许多数据块,另一个进程可能需要其中一些数据块。
②.cache buffers chains锁存器的争用——热块
热块(hot block)是cache buffer chains锁存器争用的另一个常见原因。当多个
会话重复访问一个或多个由同一个子chche buffer chains锁存器保护的块时,热块
就产生。这主要是一种应用程序问题。在大多数情况下,增加cache buffer chains
锁存器的数量对性能的改变没多大帮助。这是因为块被散列为散列存储桶和基于块地
址和散列存储桶数量的链,而不是基于cache buffer chains锁存器的数量。如果块
地址和散列存储桶的数量保持不变,则可能有少数热块仍然被一个cache buffer chains
锁存器覆盖,除非锁存器数量极大的增加。
捕获参与争用的SQL语句:
-- Using the P1RAW from the above example (00000400837D7800).
SELECT a.Hladdr,
a.File#,
a.Dbablk,
a.Tch,
a.Obj,
b.Object_Name
FROM X$bh a,
Dba_Objects b
WHERE (a.Obj = b.Object_Id OR a.Obj = b.Data_Object_Id)
AND a.Hladdr = '&
1RAW_Value'
UNION
SELECT Hladdr,
File#,
Dbablk,
Tch,
Obj,
NULL
FROM X$bh
WHERE Obj IN
(SELECT Obj
FROM X$bh
WHERE Hladdr = '&
1RAW_Value'
MINUS
SELECT Object_Id
FROM Dba_Objects
MINUS
SELECT Data_Object_Id FROM Dba_Objects)
AND Hladdr = '&P1RAW_Value'
ORDER BY 4;
展开块的方法:
◆ 通过ROWID删除并且重新插入一些行
◆ 输出表,较大的增加PCTFREE,并且输入数据。这可以最小化每个块的行数量,
将他们展开到多个块上。当然这是以存储空间作为代价,并且全表扫描会更慢。
◆ 最小化表中每个块的记录数量。这涉及转储少量数据块,用于获得每个块的当
前理想行数。手工插入你确定合适的行数,然后发布命令:
ALTER TABLE table_name MINIMIZE RECORED_PER_BLOCK。截取表和输入数据。
◆ 对于索引,对于较高的PCTFREE值可以重建他们,需要注意的是这种方法可能
增加索引的高度。
◆ 考虑见效块大小。这将对全表扫描带来极大的负面影响。
③.cache buffers chains锁存器的争用——长散列链
多个数据块可能被散列到同一个散列存储桶,他们和指针一起被连接到属于这个
散列存储桶的散列链上。对于大型数据库,散列链上块的数量可以达到数百个。进程
不得不顺序的扫描散列以获得所需的块,同时持有cache buffers chains锁存器不变。
我们称之为“追赶链”。当扫描长链时,锁存器必须被持有更厂的时间,并且可能造
成另一个进程无法实现她的cache buffers chains锁存器请求。
一直到Oracle 8.0,我们可以很容易地确定特定的散列链长度,因为散列锁存器、
散列存储桶和散列链之间的关系是1:1:1,散列链的长度等于有锁存器保护块的数量。
下面查寻报告每个散列上块的数量,带有10个或更多块的链为长链。
SELECT Hladdr,
COUNT(*)
FROM X$bh
GROUP BY Hladdr
ORDER BY 2;
通过使用_DB_BLOCK_HASH_BUSH_BUCKETS参数增加散列存储桶的数量,可以减少散
列的长度:
_DB_BLOCK_HASH_BUCKETS = 128021
_DB_BLOCK_HASH_LATCHES = 1024
Ratio = 128021 / 1024 = 125
待事件,类似于排队,Oracle使用锁存器来保护数据结构。一次只能在一个进程在获得锁存器后
修改或检查数据结构。其他需要访问该数据结构的进程必须等到它们获得锁存器后。不同于排队
的是,请求锁存器的进程不需要在队列中等待。如果获取锁存器失败,则进程仅仅等待一小段时
间就可以再次请求锁存器。这一小段等待时间成为“自旋”(spin)。如果在一次或多次自旋重复
(spin iterations)之后还没获取锁存器,进程就休眠一小段时间,然后再次尝试获取锁存器,
接下来休眠更长一段时间,直到获得锁存器。
最常见的锁存器有:cache buffer chains(高速缓存缓冲区链)、library cache(高速缓存)
和shared pool(共享池)。
1、等待参数
latch free的等待参数描述如下:
◎ P1 进程等待的锁存器地址。
◎ P2 锁存器号,同v$latchname.latch#
要查找等待锁存器的名称,可以是哟功能如下SQL语句:
SELECT *
FROM v$latchname
WHERE latch# = &
![](http://www.oracle.com.cn/images/smilies/default/20.gif)
◎ P3 尝试的次数;显示进程试图获取锁存器的次数计数器。
2、等待时间
该时间的等待时间呈指数级增长。他不包含进程为锁存器自旋(spin) 花费的时间。
以不等待模式获取的锁存器在IMMEDIATE_GETS和IMMEDIATE_MISSES列中统计。
通过愿意等待模式获取锁存器在GETS和MISSES列中有统计。特殊锁存器的GETS列在每次进程
通过愿意等待模式请求该锁存器时递增。
如果锁存器不能用,那么进程会在CPU上自旋(spin)一小段时间,重新尝试该锁存器。
v$system_Event视图中的latch free等待事件的total_waits统计追踪进程以愿意等待模式
无法获得一个锁存器的次数。v$latch视图中特殊锁存器的sleeps统计追踪进程在锁存器上睡眠
的次数。因为进程在_SPIN_COUNT次数后无法获得锁存器时没有别的事可做只好睡眠,total_times
应该等于sleeps的综合,然而,很多时候total_times大于sleeps的总合。这是因为sleeps统计
只有在锁存器GET操作成功才更新,而不是每次尝试是更新。
因为latch free等待事件总是很短,所以可以看到total_waits的一个较大的数字,这是计
数器在一段短时间内发生的等待事件。
3、常见原因、诊断和动作
锁存器征用表名另一个进程持有该锁存器过长的时间。当结合高需求量,这种争用带
来的影响将会扩大,从而明显地降低性能。锁存器争用在高度并发的环境中很普遍。可以
根据如下SQL查看进程竞争的热锁存器:
SELECT NAME,
Gets,
Misses,
Immediate_Gets,
Immediate_Misses,
Sleeps
FROM V$latch
ORDER BY Sleeps;
◎ shared pool锁存器和library cache锁存器的争用——解析
shared pool锁存器和library cache锁存器的争用主要是由于紧密的硬解析。过多
的硬解析通常出现在主要使用带有字面值的SQL语句的应用程序中。应解析是代价
昂贵的才做,并且在解析期间必须持有子library cache锁存器。
①.使用下面语句查数据库中硬解析的数量:
SELECT a.*,
SYSDATE - b.Startup_Time Days_Old
FROM V$sysstat a,
V$instance b
WHERE a.NAME LIKE 'parse%';
②.发现执行许多硬解析的当前会话:
SELECT a.Sid,
c.Username,
b.NAME,
a.VALUE,
Round((SYSDATE - c.Logon_Time) * 24) Hours_Connected
FROM V$sesstat a,
V$statname b,
V$session c
WHERE c.Sid = a.Sid
AND a.Statistic# = b.Statistic#
AND a.VALUE > 0
AND b.NAME = 'parse count (hard)'
ORDER BY a.VALUE;
③.标识作为绑定变量的合适候选的literal SQL语句:
SELECT Hash_Value,
Substr(Sql_Text, 1, 80)
FROM V$sqlarea
WHERE Substr(Sql_Text, 1, 40) IN
(SELECT Substr(Sql_Text, 1, 40)
FROM V$sqlarea
HAVING COUNT(*) > 4
GROUP BY Substr(Sql_Text, 1, 40))
ORDER BY Sql_Text;
④.正确的设置SESSION_CACHED_CURSOES参数:
每当SQL语句到达时,Oracle检查该语句是否已经在库高速缓存中。如果是的话,
只需要很少的开销就可以执行该语句;这种进程被称为软解析。在硬解吸不行时,软
解析也不好。library cache锁存器在软解析中获得。Oracle仍然必须检查语句的语法
和语义,除非该语句高速缓存在会话的游标高速缓存中。通过正确的设置
SESSION_CACHED_CURSOES参数,可以减少library cache锁存器持有时间。然而最好的
方法是减少软解析的数量,这只可通过应用程序完成。
通过在v$sqlarea视图中查找带有大量parse_calls的语句,你可以找到令人不
愉快的语句。
如果发现数据库具有长共享池空闲列表,并且应用程序使用literal SQL,那么就
应该考虑减少SHARED_POOL_SIZE。这将减少share pool锁存器的争用。
也应该使用dbms_shared_pool.keep过程钉住共享池中可重用的对象。
v$db_object_cache视图具有保存相关对象的信息。
◎ library cache锁存器的争用——带有高版本数的语句
Oracle使用多个子游标来区分一些SQL语句,这些SQL语句具有相同的字符,但是不能
被共享,因为他们引用不同的底层对象。例如:如果数据库有三个Customer表,并且
每个表属于不同的模式,那么每个拥有者发布的SELECT * FROM Customer语句将具有
相同的散列值,但是具有不同的子段数量。当被解析语句散列值匹配带有高的子段数
或版本数的语句散列值时,Oracle必须比较语句和所有的现有版本。必须在检查期间
持续持有library cache锁存器,着可能造成其他进程无法实现他们的library cache
锁存器请求。通过在数据库中使用唯一的对象名,可以最小化这个问题。
查询列出v$sqlarea中版本数大于20的所有SQL语句:
SELECT Version_Count,
Sql_Text
FROM V$sqlarea
WHERE Version_Count > 20
ORDER BY Version_Count,
Hash_Value;
◎ cache buffer chains锁存器
在将数据读入SGA时,他们的缓冲区头被防止在悬挂散列存储桶的链表中(散列链)。
这种内存结构由大量子cache buffers chains锁存器(也称散列锁存器或CBC锁存器)
保护。希望在添加、删除、搜索、检查、读取、或修改块的进程必须首先获得cache
buffers chains锁存器,从而保护链上的缓冲区。这样就可以保证独占访问,并防
止其它进程接下来读取或改变同一个链。为了完整性牺牲了并发性。通过设置
_DB_BLOCK_HASH_LATCHS参数可以调整散列锁存器数量。
如下SQL取实例中散列锁存器的数量:
SELECT COUNT(DISTINCT(Hladdr)) FROM X$bh;
①.cache buffers chains锁存器的争用——底效率的SQL语句
低效率的SQL语句是cache buffers chains锁存器争用的主要原因。当和高并发
率混合在一起时,花费在latch free等待事件上的时间可能更多。在某些环境中,
应用程序打开执行相同的低效率SQL语句的多个并发会话,并且这些SQL语句都没法得
到相同的数据集,这种情况下相当普遍。
如果集注下面3个方面,你可以做的很好:
◆ 每个逻辑读取需要一个latch gey操作和一个CPU
◆ 从latch get例程中获得的唯一方法是获得锁存器
◆ 在任意时刻,只有一个进程可以拥有cache buffer链,并且这个锁存器覆盖
许多数据块,另一个进程可能需要其中一些数据块。
②.cache buffers chains锁存器的争用——热块
热块(hot block)是cache buffer chains锁存器争用的另一个常见原因。当多个
会话重复访问一个或多个由同一个子chche buffer chains锁存器保护的块时,热块
就产生。这主要是一种应用程序问题。在大多数情况下,增加cache buffer chains
锁存器的数量对性能的改变没多大帮助。这是因为块被散列为散列存储桶和基于块地
址和散列存储桶数量的链,而不是基于cache buffer chains锁存器的数量。如果块
地址和散列存储桶的数量保持不变,则可能有少数热块仍然被一个cache buffer chains
锁存器覆盖,除非锁存器数量极大的增加。
捕获参与争用的SQL语句:
-- Using the P1RAW from the above example (00000400837D7800).
SELECT a.Hladdr,
a.File#,
a.Dbablk,
a.Tch,
a.Obj,
b.Object_Name
FROM X$bh a,
Dba_Objects b
WHERE (a.Obj = b.Object_Id OR a.Obj = b.Data_Object_Id)
AND a.Hladdr = '&
![](http://www.oracle.com.cn/images/smilies/default/20.gif)
UNION
SELECT Hladdr,
File#,
Dbablk,
Tch,
Obj,
NULL
FROM X$bh
WHERE Obj IN
(SELECT Obj
FROM X$bh
WHERE Hladdr = '&
![](http://www.oracle.com.cn/images/smilies/default/20.gif)
MINUS
SELECT Object_Id
FROM Dba_Objects
MINUS
SELECT Data_Object_Id FROM Dba_Objects)
AND Hladdr = '&P1RAW_Value'
ORDER BY 4;
展开块的方法:
◆ 通过ROWID删除并且重新插入一些行
◆ 输出表,较大的增加PCTFREE,并且输入数据。这可以最小化每个块的行数量,
将他们展开到多个块上。当然这是以存储空间作为代价,并且全表扫描会更慢。
◆ 最小化表中每个块的记录数量。这涉及转储少量数据块,用于获得每个块的当
前理想行数。手工插入你确定合适的行数,然后发布命令:
ALTER TABLE table_name MINIMIZE RECORED_PER_BLOCK。截取表和输入数据。
◆ 对于索引,对于较高的PCTFREE值可以重建他们,需要注意的是这种方法可能
增加索引的高度。
◆ 考虑见效块大小。这将对全表扫描带来极大的负面影响。
③.cache buffers chains锁存器的争用——长散列链
多个数据块可能被散列到同一个散列存储桶,他们和指针一起被连接到属于这个
散列存储桶的散列链上。对于大型数据库,散列链上块的数量可以达到数百个。进程
不得不顺序的扫描散列以获得所需的块,同时持有cache buffers chains锁存器不变。
我们称之为“追赶链”。当扫描长链时,锁存器必须被持有更厂的时间,并且可能造
成另一个进程无法实现她的cache buffers chains锁存器请求。
一直到Oracle 8.0,我们可以很容易地确定特定的散列链长度,因为散列锁存器、
散列存储桶和散列链之间的关系是1:1:1,散列链的长度等于有锁存器保护块的数量。
下面查寻报告每个散列上块的数量,带有10个或更多块的链为长链。
SELECT Hladdr,
COUNT(*)
FROM X$bh
GROUP BY Hladdr
ORDER BY 2;
通过使用_DB_BLOCK_HASH_BUSH_BUCKETS参数增加散列存储桶的数量,可以减少散
列的长度:
_DB_BLOCK_HASH_BUCKETS = 128021
_DB_BLOCK_HASH_LATCHES = 1024
Ratio = 128021 / 1024 = 125
LATCHES是一种低级的同步锁机制,用以维持某些查询和执行操作得顺序。通过它来达成对系统得SGA中共享内存结构的保护。当请求得到LATCH但它已被其他进程占住时,将产生一条FREE MISS记录。多数LATCH问题关联到不使用绑定变量(LIBRARY CACHE LATCH),重做日志生成问题(REDO ALLOCATION LATCH),内存缓冲区竞争问题(CACHE BUFFERS LRU CHAIN)和内存缓冲区中“过热”的数据块(CHCHE BUFFERS CHAIN)。当LATCH错失率超过0.5%时,需要仔细研究下了(METALINK ORACLE.COM/SUPPORT )。在STATSPACK报告中,等待事件LATCH FREE很高时,下面内容查看有关LATCH的问题。
在Statspack报告中的Latch Activity 部分将可以得到关于这些Latch的更具体的信息。Get Requests、Pct Get Miss和Avg Slps/Miss(关于睡眠和错失)是针对“Willing-To-Wait”Latches请求的统计,而NoWait Requests和Pct NoWait Miss则是针对“No-Wait”Latches请求。相对于两种Latch请求的Pct Miss都应该接近于0.0。
分析Latch问题时,v$latch视图十分有帮助,v$latchholder、v$latchname和v$latch_children等视图也很有帮助。
当Statspack报告中,等待事件一节里的“Latch Free”项很高的数值时,在报告中关于Latch的段落内一定可以发现需要研究的问题。下面内容将可以查看这些有关Latch的问题。
Library Cache and Shared Pool
库缓存Latch为对库中对象的访问请求排队,每当执行SQL或PL/SQL存储过程、包、函数和触发器时,这个Latch即被用到。Parse操作中此Latch也会被频繁使用。自9i开始,增加了7个子Latch。共享池太小或SQL语句不能重用时,会发生“Shared Pool”、“Library Cache Pin”或“Library Cache”Latch竞争。SQL语句不可再用往往是因为未使用绑定变量,共享池里随处可见很相像但又不一样的SQL语句,而增加池的大小只会把Latch的问题搞得更糟。可以设置初始化参数CURSOR_SHARING=FORCE 减少绑定变量未使用的问题。然而,共享池和库缓存的Latch问题在后者对需处理的大批SQL语句而言设置太小,需要分配更多内存的情况下也会发生。欲将SQL或PL/SQL语句装入内存而首先释放部分空间的操作占据Latch,令其他用户等待。可以通过增大共享池来减缓此种竞争,还可以通过使用DBMS_Shared_pool.keep存储过程在内存种固定大的SQL或PL/SQL语句来解决这个问题。
Redo Copy
重做拷贝Latch的数量在缺省情况下是2*CPU_COUNT,但可通过_LOG_SIMULTANEOUS_COPIES的初始化参数来重新设置。增大此参数可以帮助减缓对重做拷贝Latch的竞争。重做拷贝Latch用来从PGA向重做日志缓冲区重做记录。
Redo Allocation
对Redo Allocation Latch(分配重做日志缓冲区中的空间)的竞争可以通过选用NOLOGGING的选项来减缓,该选项可以减轻日志缓冲区的负荷。另外,应当避免不必要的提交。
Row Cache Objects
“Row Cache Objects”Latch的竞争通常意味数据字典的竞争,它同时也可能是过度Parsing依赖于公共同义词SQL语句的症状。增大共享池一般可以解决此问题。这个办法往往用来解决库缓存Latch的问题,而在那个问题解决好了的前提下,“Row Cache Objects”Latch的竞争通常就不会成为一个问题。
Cache Buffers Chains
扫描SGA中的内存缓冲区时需要内存缓冲区链Latch。缓冲区中“过热”的数据块造成了缓冲区链Latch的问题,“过热”的数据块同时也是可能时调整差的SQL语句所导致的症状。“过热”的记录创建了“过热”的块,也就导致了块里其他记录的问题和映射到该块地址上的hash链的问题。为了定位“热块”,可以查询v$latch_children视图来确定块地址,并通过该视图与x$bh视图的连接来确定此Latch保护下的所有数据块(此将确定受“热块”影响的全部数据块)。以在x$bh视图里找到的file#和dbablk,可以进而查询dba_extents以确定受影响的对象。如果“热块”在某索引上,转而采用反向关键字索引即可把连续排放的记录搬到其他数据块中,它们也就不再会被“热块”一连串地锁住了。如果“热块”时索引的“根”块,那么反向索引就帮不上忙了,把_db_block_hash_buckets设置成比缓冲区数(DB_CACHE_SIZE/DB_BLOCK_SIZE)的2倍大的最小质数的值通常能够清除此问题的干扰。
Cache Buffers LRU Chain
扫描全部内存缓冲区块的LRU(最近最少使用)链时要用到内存缓冲区LRU链Latch。大小的内存缓冲区、过大的内存缓冲区吞吐量、过多的内存中进行的排序操作、DBWR速度跟不上工作负载等全都可能成为导致内存缓冲区LRU链Latch严重竞争的罪魁祸首:调整导致过量逻辑度的查询!可以增大初始化参数DB_BLOCK_LRU_LATCHES以得到多个LRU Latches,如此可减少竞争。非SMP(对称多处理器)系统仅需要惟一的LRU Latch,而在SMP系统的情况下,Oracle自动把LRU Latch的数目设置成1/2CPU数。对于一个数据库写进程,需要分配给它至少一个LRU Latch,如果需要增大数据库写进程的数目,则不能忘记同时增加LRU Latch的数目。