Oracle 外部数据库上的物化视图无法在指定时间刷新-SQL*Net来自dblink的更多数据
我们使用在Oracle上运行的基于web的服务。他们严格要求只允许选择ODBC访问。我们所做的一些报告没有很好地被公司提供的视图所解释,因此我们使用Oracle 11g的express edition建立了一个db_链接,并使用refresh:specify设置将一些更重要的查询重写为物化视图,以每小时重新运行查询,这对于我们的目的来说是最新的。到目前为止一切都很好 我注意到一些MVs会停止刷新,没有真正的模式。进一步调查,我们通过db_link连接到的外部数据库有时无法完成查询,刷新过程耐心地等待事件“SQL*Net更多数据来自dblink” 下面是我运行的查询,以获取有关卡住的刷新会话和三个似乎是卡住的刷新语句的会话的数据:Oracle 外部数据库上的物化视图无法在指定时间刷新-SQL*Net来自dblink的更多数据,oracle,oracle11g,materialized-views,Oracle,Oracle11g,Materialized Views,我们使用在Oracle上运行的基于web的服务。他们严格要求只允许选择ODBC访问。我们所做的一些报告没有很好地被公司提供的视图所解释,因此我们使用Oracle 11g的express edition建立了一个db_链接,并使用refresh:specify设置将一些更重要的查询重写为物化视图,以每小时重新运行查询,这对于我们的目的来说是最新的。到目前为止一切都很好 我注意到一些MVs会停止刷新,没有真正的模式。进一步调查,我们通过db_link连接到的外部数据库有时无法完成查询,刷新过程耐心地
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的更多数据”的卡住会话并终止它们吗?”我想要的行为是,这种刷新更具弹性-如果超时,我希望它重新开始,然后重试
我不认为找出外部db停止执行这些查询的原因会有多大的收获——提供者提供选择特权,但很清楚不想支持/解决出现的任何问题
我读过关于在SQLNET.ora文件中设置idle_time和更改set SQLNET.EXPIRE_time的内容,但我没有感觉到这是正确的方法,因为连接不是空闲的,它们是活动的,但会无限期地等待,而且这些会话是由数据库本身启动的,这是一个复杂的因素
如何使此刷新更具弹性/自动终止这些等待已久的刷新 不要仅仅为了在远程Oracle实例的mat视图上执行刷新而通过dblink进行连接。只需设置一个调度程序作业,在与视图相同的实例上启动刷新 您不需要打开连接并等待刷新完成。这更像是一个自动化的管理工作,而不是外部客户机应该启动和照看的工作。如果您需要检查它的状态,您可以检查dba\U调度程序\U作业、dba\U调度程序\U作业\U日志、dba\U调度程序\U运行\U详细信息、所有\U调度程序\U运行\U作业等。除此之外,这些将告诉您很多信息
有关一些好的示例,请参见。如果您使用的是11g,请使用其他增强功能。@tbone,感谢dbms\u调度程序资源。我最终做的是构建一个计划作业,该作业将查找卡住的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;
/
这个how-to很有帮助,尽管它没有对计划的作业使用新的语法:最近,我们的物化视图完整刷新过程也遇到了同样的问题。通过进一步优化刷新所需的网络时间(从约25分钟到约2分钟),将问题降至最低;尽管端到端刷新仍然需要大约10分钟。以下是我们所做的: 假设您的数据源查询已经优化,您可以进一步缩短刷新时间,如下所述: 步骤1:在无记录模式下创建物化视图,在存在原始物化视图的计算机上没有索引和自动刷新计划 步骤2:在日志记录模式下重新创建原始物化视图,将上述物化视图作为本地数据源,并具有所需的索引和无自动刷新计划 步骤3创建执行以下任务的刷新过程: 1-刷新在NOLOGGING模式下创建的物化视图 2-验证本地和远程数据源之间的数据完整性 3-如果已验证,则对在记录模式下创建的物化视图进行完全刷新 我不是专家,如果我的任何假设不正确,请纠正我。我已经在我的博客文章中记录了这个过程
免责声明:这是我的个人博客我认为我不够清楚-MV不在远程Oracle实例上-它是本地的。所以MV已经创建了dbms_刷新作业来刷新这些表-问题是有时它们无法完成,并且永远挂起。@Andrew:我知道你已经设置了刷新作业,但你似乎正在通过dblink从客户端启动刷新,对吗?如果是这样,我建议您设置一个Oracle DBMS_调度程序作业来启动服务器端的刷新
这对你有用。不过,对我来说,取消会话并不能真正解决为什么这些刷新不能在指定的15分钟内完成的问题?。您可能还需要验证是否没有阻止刷新视图的阻塞会话。请参见我的回答:@Andrew在您杀死他们时,作业会自动重新安排吗?@Kitex it will-作业在正常时间运行。@t如果您就在这里,最终所有这些都会被重新处理。我不是共享全局区域内部工作的专家,但是使用dblink的MVs会生成大量的重做。这在其他地方造成了性能问题。使用dblinks的mv已被重写为自定义PL/SQL刷新作业。比如说变成了。如果其他人发现了这一点,我会尽可能避免接触数据库链接的MVs。