You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

dbms_stats.gather_table_stats并行收集子表统计信息引发死锁问题咨询

Oracle 12.1 RAC并行收集子表统计信息死锁问题分析与解决

这是预期行为吗?

没错,在Oracle 12.1的2节点RAC环境中,这种因并行收集关联子表统计信息引发的死锁属于已知场景(该版本机制局限导致的预期问题)

具体来说,当两个子表共享同一个父表的主键作为外键时,并行统计收集进程运行时会尝试获取父表上的相关锁——比如用于验证外键完整性的锁,或是统计信息收集所需的共享/排他锁。在RAC多节点环境下,不同节点上的并行进程可能因锁的获取顺序不一致,形成循环等待的局面,最终触发死锁。Oracle在12.1版本中,针对外键关联表的并行统计收集锁机制存在设计局限,跨节点的这类锁争用场景是有官方记录的已知问题。

解决建议

针对这个问题,你可以尝试以下几种方案:

  • 串行执行统计收集任务:最简单的方式就是避免同时并行收集这两个子表的统计信息,改为先收集其中一个子表,等任务完全结束后再启动另一个的收集任务,从根源上避免锁争用。
  • 使用NO_VALIDATE参数跳过外键验证:在调用DBMS_STATS.GATHER_TABLE_STATS时,添加NO_VALIDATE => TRUE参数,这个参数会让Oracle跳过外键关系的验证步骤,从而避免获取父表的相关锁。示例代码如下:
    EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCHEMA_NAME', TABNAME => 'CHILD_TABLE_1', NO_VALIDATE => TRUE);
    EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCHEMA_NAME', TABNAME => 'CHILD_TABLE_2', NO_VALIDATE => TRUE);
    
    注意:如果业务需要确保外键有效性,后续可以单独执行ALTER TABLE CHILD_TABLE_1 VALIDATE CONSTRAINT FK_NAME;来验证外键。
  • 升级数据库版本:Oracle在12.2及后续版本中,对统计信息收集的锁机制做了针对性优化,尤其是RAC环境下外键关联表的场景,这类死锁问题的发生概率被大幅降低。如果业务允许,升级到更高版本是一劳永逸的解决方案。
  • 调整并行度或指定单节点执行:可以将统计收集的并行度设置为1(DEGREE => 1),或者通过指定服务名让两个子表的统计收集任务都在同一个节点上执行,减少跨节点的锁竞争。
  • 锁定父表统计信息:如果父表的统计信息近期没有发生变化,你可以先手动锁定父表的统计信息,再收集子表的统计信息。收集完成后再解锁,这样子表的统计收集进程就不会尝试获取父表的统计相关锁。示例命令:
    -- 锁定父表统计
    EXEC DBMS_STATS.LOCK_TABLE_STATS(OWNNAME => 'SCHEMA_NAME', TABNAME => 'PARENT_TABLE');
    -- 收集子表统计
    EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCHEMA_NAME', TABNAME => 'CHILD_TABLE_1');
    EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCHEMA_NAME', TABNAME => 'CHILD_TABLE_2');
    -- 解锁父表统计
    EXEC DBMS_STATS.UNLOCK_TABLE_STATS(OWNNAME => 'SCHEMA_NAME', TABNAME => 'PARENT_TABLE');
    

内容的提问来源于stack exchange,提问作者Rupesh

火山引擎 最新活动