适用于:
Oracle Database - Enterprise Edition - 版本 10.2.0.1 到 11.2.0.4 [发行版 10.2 到 11.2]
本文档所含信息适用于所有平台
目标
本文档的目的是帮助诊断" enq: TX - index contention"问题
解决方案`
当运行 OLTP 系统时,当应用程序并发很高时,可能会看到与表相关的索引上的高 TX 队列争用。这通常发生在应用程序同时并发执行大量 INSERT 和 DELETE 时。 对于 RAC 系统,并发的 INSERT 和 DELETE 可能发生在所有的实例中。
原因是在将新行插入索引时,索引块会分裂。操作将不得不等待模式4的 TX 锁,直到进行索引分裂的会话完成操作。
当在索引块中找不到需要插入新行的空间时,会话将启动索引分裂。开始分裂之前,它将清除块中的所有键,以检查在被删除的块中是否有足够的空间。
分裂操作必须做以下活动:
o 分配一个新的块。 o 将一定百分比的行复制到新索引块。 o 将新索引块添加到索引结构并提交操作。
在 RAC 环境中,由于包括全局缓存操作,这可能是一项昂贵的操作。如果分裂发生在分支或根块级别,则影响将更大。
原因:
最可能的原因是:
o 从应用程序大量访问的表的索引。
o 单向生长的表列索引。也就是说,大多数索引插入仅在索引的右边缘出现。
o 已执行大量数据清除,并紧接着又发生了高并发插入。
识别热索引:
有争用的索引可以从问题时段的 AWR 报告中确定。
Top 5 Timed Events: Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class en: TX - index contention 89,350 40,991 459 63.3 Concurrency db file sequential read 1,458,288 12,562 9 19.4 User I/O cpu time 5,352 8.3 Instance Activity Stats: Statistic Total per Second per Trans branch node splits 945 0.26 0.00 leaf node 90-10 splits 1,670 0.46 0.00 leaf node splits 35,603 9.85 0.05
而这些对象可以从 V$SEGMENT_STATISTICS 或从 AWR 报告中的“Segments by Row Lock Waits”或“Segments by ITL Waits”或“Service ITL Waits”中找到。
Segments by Row Lock Waits: Owner Tablespace Object Name Obj.Type Row Lock Waits % of Capture ACSSPROD ACSS_IDX03 ACSS_ORDER_HEADER_PK INDEX 3,425 43.62 ACSSPROD ACSS_IDX03 ACSS_ORDER_HEADER_ST INDEX 883 11.25 ACSSPROD ACSS_IDX03 ACSS_ORDER_HEADER_DT INDEX 682 8.69 Segments by ITL Waits Owner Tablespace Name Object Name Subobject Name Obj. Type ITL Waits % of Capture ACSSPROD ACSS_IDX03 ACSS_ORDER_HEADER_PK INDEX 6 50.00 ACSSPROD ACSS_IDX03 ACSS_ORDER_HEADER_ST INDEX 3 25.00 ACSSPROD ACSS_IDX03 ACSS_ORDER_HEADER_DT INDEX 3 25.00
解决方案:
这里的解决方案是调整索引,避免对少量块进行大量访问。
以下是我们可以尝试的选项:
• 将 AWR 报告的'Segments by Row Lock Waits'中列出的索引重建为反向键索引或散列分区
例如:
CREATE INDEX <index name> ON <column> REVERSE;
从性能调优指南 -
反向键索引旨在消除插入应用程序上的索引热点。 这些指标非常适合插入操作的性能。 但它的缺点是它可能影响索引范围扫描的性能。
http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/design.htm#sthref112
在多用户 OLTP 环境中,如果索引中的少量叶子索引块并发很高,那么哈希分区方法可以提高索引的性能。 在某些 OLTP 应用程序中,索引插入只发生在索引的右边缘。 当索引定义为单调递增的列时,可能会发生这种情况。 在这种情况下,由于索引页,缓冲区,更新锁存器和附加索引维护活动的争用,索引的右边缘成为热点,从而导致性能下降。
http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/data_acc.htm#i2678
建议在将索引重新构建为反向键索引或哈希分区后,测试应用程序的性能。
• 考虑增加 sequence 的 CACHE 大小
alter sequence <owner>.<seq name> cache <required value>;
当我们使用单调增加的 sequence 来填充列值时,具有高序列值的叶子索引块将随着每个插入而改变,这使得它成为块分裂的热块和潜在候选。
使用 CACHE SIZE(并且可能使用 NOORDER 选项),每个实例将使用具有不同范围的 sequence,减少索引键插入同一组叶子索引块。
• 在大量数据清除后,重建或 shrink 相关联索引
如果有大量的数据清除(删除)操作,通过 alter index rebuild 或 alter index shrink 命令重建或缩小关联的索引有助于减少等待。
• 增加索引的 PCT_FREE
高的 PCT_FREE 有助于避免索引块的 ITL 争用。当一个区块内的所有可用 ITL 当前正在使用中,而且 Oracle 的 PCT_FREE 区域没有足够的空间来动态分配新的 ITL 插槽,那么将发生 ITL 争用。
参考
BUG:8735005 - SLOW INSERT - POSSIBLY DUE TO INDEX BLOCK SPLIT BUG:19023318 - INDEX BLOCK SPLIT CAN CAUSE ENQ:TX-INDEX CONTENTION
引用自:"enq: TX - index contention" (文档 ID 2331575.1)