3

我们使用在 Oracle 上运行的基于 Web 的服务。他们严格地只允许 SELECT-only ODBC 访问。我们所做的一些报告并没有被公司提供的视图很好地解释,因此我们使用 Oracle 11g 的快速版设置了一个 db_link,并使用刷新将一些更重要的查询重写为物化视图:指定设置以每小时重新运行查询,这对于我们的目的来说已经足够了。到目前为止一切都很好。

我注意到一些 MV 会停止刷新,背后没有真正的模式。进一步调查,它不时发现外部数据库(我们通过 db_link 连接的那个)不时完成查询,刷新过程耐心等待事件“SQL*Net more data”从 dblink' 无限期地。

这是我运行的查询,以获取有关卡住的刷新会话和似乎卡住刷新语句的三个会话的数据:

select a.username, a.osuser, a.sid, a.serial#, b.spid, a.seconds_in_wait, 
       a.event, a.state, a.wait_class
from v$session a, v$process b
where a.paddr = b.addr
and a.seconds_in_wait > 500 and a.username is not null;

USERNAME    OSUSER  SID SERIAL# SPID    SECONDS_IN_WAIT EVENT                         STATE   WAIT_CLASS
KIPP_NWK    SYSTEM  27  7904    2704    161991          SQL*Net more data from dblink WAITING Network
KIPP_NWK    SYSTEM  35  2469    3880    139489          SQL*Net more data from dblink WAITING Network
KIPP_NWK    SYSTEM  37  6051    1408    40860           SQL*Net more data from dblink WAITING Network

因此,我认为我的问题是“关于脚本的任何建议,该脚本将定期(例如,每小时)扫描事件类型“来自 dblink 的更多数据”的卡住会话并终止它们?对我来说,期望的行为是这种刷新更有弹性——如果超时,我希望它重新开始并尝试,再试一次......

我不认为弄清楚为什么外部数据库停止执行这些查询会很有成效——提供者提供了选择权限,但很清楚不想支持/解决出现的任何问题。

我在 sqlnet.ora 文件中阅读了有关设置 idle_time 和更改设置 SQLNET.EXPIRE_TIME 的信息 - 但我不认为这是正确的方法,因为连接不是空闲的,它们是活动的但无限期等待,以及这些会话由数据库本身发起的复杂因素。

如何使此刷新更具弹性/自动终止这些等待已久的刷新?

4

3 回答 3

1

不要仅仅为了在远程 Oracle 实例上的 mat 视图上执行刷新而通过 dblink 进行连接。只需设置一个调度程序作业即可在与视图相同的实例上启动刷新。

您不需要打开连接并等待刷新完成。这更像是一项自动化的管理工作,而不是外部客户端应该启动和照看的工作。如果需要查看它的状态,可以查看dba_scheduler_jobs、dba_scheduler_job_log、dba_scheduler_run_details、all_scheduler_running_jobs等(不止这些,但这些会告诉你很多)。

请参阅此处以获取一些很好的示例。如果您使用的是 11g,其他增强功能。

于 2011-07-18T16:30:09.743 回答
1

最近,我们的物化视图完整刷新过程也遇到了同样的问题。通过进一步优化刷新所需的网络时间(从大约 25 分钟到大约 2 分钟;尽管端到端刷新仍然需要大约 10 分钟),该问题已最小化。这是我们所做的:

假设您的数据源查询已经优化,您可以进一步减少刷新时间,如下所述:

步骤 1)在存在原始物化视图的机器上以 NOLOGGING 模式(没有索引和自动刷新计划)创建物化视图

步骤2)以上述物化视图作为本地数据源,以LOGGING模式重新创建原始物化视图(具有所需索引且无自动刷新计划)

步骤 3)创建执行以下任务的刷新过程:

1-刷新在NOLOGGING模式下创建的物化视图

2-验证本地和远程数据源之间的数据完整性

3-如果经过验证,则完全刷新物化视图(在 LOGGED 模式下创建)

我不是专家,所以如果我的任何假设不正确,请纠正我。我在我的博客文章Oracle Materialized View Complete Refresh over Database Link中记录了这个过程

免责声明:这是我的个人博客

于 2015-10-25T11:41:06.493 回答
0

@tbone,感谢 dbms_scheduler 资源。我最终做的是构建一个计划的作业来查找卡住的 dblink 刷新并终止它们。它似乎运作良好。

我创建了这个存储过程,它杀死了在 SQL*Net 上等待 10 分钟的作业,更多来自 dblink 的数据:

create or replace procedure kill_stuck_refresh
as
begin     
    for x in (  
            select username, osuser, sid, serial#, seconds_in_wait, 
            event, state, wait_class
            from v$session
            where username is not null 
                  and seconds_in_wait > 600 
                  and event = 'SQL*Net more data from dblink'  
        ) loop  
        execute immediate 'alter system disconnect session '''|| x.sid  
                     || ',' || x.serial# || ''' immediate';
        dbms_output.put_line( 'Alter session done' );             
    end loop;  
end;  

然后是这个定期运行存储过程的 dbms 作业:

BEGIN
DBMS_SCHEDULER.CREATE_JOB(job_name        => 'kill_stuck_refresh_jobs',
                          job_type        => 'STORED_PROCEDURE',
                          job_action      => 'kill_stuck_refresh',
                          start_date      => sysdate,
                          repeat_interval => 'freq=minutely; interval=15',
                          end_date        => NULL,
                          enabled         => TRUE,
                          comments        => 'calls kill_stuck_refresh every 15 minutes');
END;
/

这个方法很有帮助,即使它不使用新语法来安排作业:http ://baurdotnet.wordpress.com/2010/11/11/oracle-job-session-killer/

于 2011-07-19T23:07:20.817 回答