2016-08-25 51 views
9

我们的客户之一有一个Oracle 10.2.0.5 RAC(HPUX)和两个SQL Server 2012(Windows server 2008R2)。我们正在帮助他们将数据从Oracle发布到SQL Server。他们还需要知道哪些行被添加,更新和删除,但他们不想修改他们的应用程序。Oracle的SQLServer出版物

整个事情是这样的:

Oracle作为出版商 - > SQL Server中的作为总代理 - >作为 用户

我们的DBA已通过SSMS配置了所有的DB SQL服务器B (SQL Server Management Studio)像这样Create a Publication from an Oracle Database。它运行了好几天。但甲骨文的表现越来越差。最后,我们必须停止Oracle的数据发布。

事实证明,SSMS将在Oracle中创建一个名为“HREPL”的程序包,该程序包有一个名为“PollEnd”的过程。 “PollEnd”将以非常高的频率执行以删除表“HREPL_ARTICLE1LOG_1”中的数据。但“PollEnd”的执行时间会随着时间增加。最后,执行时间比执行时间长,表被锁定,Oracle的性能会非常差。

而我们卡在这里。

有没有人有任何想法如何解决这个问题?请帮忙!

的 “PollEnd” 过程:

----------------------------------------------------------------------------------- 
-- 
-- Name: PollEnd 
-- Purpose: PollEnd request signifies that the change entries identified with the current 
--   interval have been successfully entered into the store and forward database 
--   and can be deleted from the article log tables. 
-- Input: 
--   argLSN   IN RAW(10)  LSN from distributor that was associated 
--           with this poll interval 
-- Output: 
-- Notes: This request causes those entries of the article log tables represented in the 
--   Poll Table and having the current pollid to be deleted from both their article log 
--   tables and from the Poll Table. The last request value is updated to reflect a 
--   PollEnd request. 
-- 
----------------------------------------------------------------------------------- 
PROCEDURE PollEnd 
(
    argLSN  IN RAW 
) 
AS 
    SQLCommand  VARCHAR2(500); 
    LogTable  VARCHAR2(255); 
    CurrentPollID NUMBER; 
    TableIDs  number_tab; 
    InstanceIDs  number_tab; 
    IDCount   BINARY_INTEGER; 
    PublisherLSN RAW(10); 

BEGIN 
    -- Put the published tableIDs in a PL/SQL table of IDs 
    HREPL.GetTableIDs(TableIDs, InstanceIDs); 

    -- Get the current Poll ID 
    SELECT Publisher_CurrentPollid INTO CurrentPollID FROM HREPL_Publisher; 

    IDCount := TableIDs.COUNT; 
    -- For each table represented in the ID list 
    FOR id_ind IN 1 .. IDCount 
    LOOP 

     LogTable := REPLACE(REPLACE(ArticleLogTemplate, MatchString, TO_CHAR(TableIDs(id_ind))), 
                 MatchStringY, TO_CHAR(InstanceIDs(id_ind))); 

     BEGIN 
      -- Generate command to delete from the article log those entries appearing in the 
      -- Poll Table with the current PollID 
      SQLCommand := 'DELETE FROM ' || LogTable || ' l ' || 
           'WHERE EXISTS (SELECT p.POLL_POLLID FROM HREPL_POLL p ' || 
           '    WHERE CHARTOROWID(l.ROWID) = p.Poll_ROWID ' || 
           '    AND p.Poll_PollID = :Pollid)'; 

      HREPL.ExecuteCommandForPollID(SQLCommand, CurrentPollID); 

     EXCEPTION 
      WHEN OTHERS THEN NULL; 
     END; 
    END LOOP; 

    FOR POLLID IN (SELECT CurrentPollid FROM DUAL) 
    LOOP 
     -- Delete from HREPL_Event those entries appearing in the Poll Table 
     -- with the current PollID. 
     DELETE FROM HREPL_Event e 
     WHERE EXISTS (SELECT p.POLL_POLLID FROM HREPL_POLL p 
         WHERE CHARTOROWID(e.ROWID) = p.Poll_ROWID 
         AND p.Poll_PollID = POLLID.CurrentPollID); 

     -- Delete entries from the Poll Table having the current Pollid 
     DELETE FROM HREPL_Poll 
     WHERE Poll_PollID = POLLID.CurrentPollID; 
    END LOOP; 

    -- Drop all views associated with articles that are marked as UnPublishPending. 
    -- Note: We cannot perform these drops in UnPublish table, since UnPublish 
    --  table can execute concurrently with PollBegin and the querying 
    --  of published tables by the log reader. PollEnd, however, executes 
    --  synchronously with respect to these activities, so can be used 
    --  to cleanup log tables and views that are no longer needed. 
    HREPL.CleanupLogsandViews; 

    -- Mark the last request as PollEnd, and update the Publisher LSN 
    -- to reflect the LSN committed at the publisher. 
    UPDATE HREPL_Publisher 
    SET Publisher_PollInProcess = NoPollInProcess, 
     Publisher_LSN = argLSN; 

    -- Commit transaction 
    COMMIT; 

EXCEPTION 
    WHEN OTHERS THEN 
     ROLLBACK; 
     RAISE; 

END PollEnd; 

编辑01:

全包是在这里:HREPL

编辑02:

最后我们给向上。 MS和Oracle相互指责。

我们试图用ogg将数据从oracle复制到sql server,这也是一团糟。

现在我们试图使用ogg将数据从oracle复制到oracle。

感谢您的帮助。

+1

这些问题很难通过查看单个程序来诊断。你碰巧知道你的'PollEnd'程序的哪一部分增加了执行时间?而且,'IDCount'有多大?随着时间的推移,这个数字会大大增加吗也可能(不相关),为什么循环通过DUAL表?该表永远不应该有多行。 – MJH

+1

数据需要在下游服务器上保持最新状态? – Bohemian

+0

@MJH我上传了完整的包,添加我会问我们的dba你需要的参数。 – neohope

回答

0

将您的DELETE ... WHERE EXISTS (...)转换为使用多表删除语法。

SQLCommand := 'DELETE l' || 
    ' FROM HREPL_POLL, ' || LogTable || 
    ' l WHERE CHARTOROWID(l.ROWID) = p.Poll_ROWID ' || 
    ' AND p.Poll_PollID = :Pollid)'; 

创建所涉及的每个表的函数索引:

CREATE INDEX MYTABLE_CHARTOROWID ON MYTABLE(CHARTOROWID(ROWID)); 

再进一步下跌:

DELETE e 
FROM HREPL_POLL p, HREPL_Event e 
WHERE CHARTOROWID(e.ROWID) = p.Poll_ROWID 
    AND p.Poll_PollID = POLLID.CurrentPollID; 

最后,删除完全由LOOP过双 - 它绝对没有任何;只需使用CurrentPollid直接执行它内部的代码即可。

+0

如果你摆脱了无意义的循环,你必须删除循环内的'POLLID.'引用。无论如何,这个回路不太可能对整体表现产生显着影响。 –

+0

@ammoQ我对代码的厌恶影响了我的理性方面。我修改了我的评论,直接使用'CurrentPollid'。干杯。 – Bohemian

0

一些加入条件似乎不合理,您可能对此版本更加幸运 - 如果您在生产环境中尝试它,那么您可以自行承担风险!

----------------------------------------------------------------------------------- 
-- 
-- Name: PollEnd 
-- Purpose: PollEnd request signifies that the change entries identified with the current 
--   interval have been successfully entered into the store and forward database 
--   and can be deleted from the article log tables. 
-- Input: 
--   argLSN   IN RAW(10)  LSN from distributor that was associated 
--           with this poll interval 
-- Output: 
-- Notes: This request causes those entries of the article log tables represented in the 
--   Poll Table and having the current pollid to be deleted from both their article log 
--   tables and from the Poll Table. The last request value is updated to reflect a 
--   PollEnd request. 
-- 
----------------------------------------------------------------------------------- 
PROCEDURE PollEnd 
(
    argLSN  IN RAW 
) 
AS 
    SQLCommand  VARCHAR2(500); 
    LogTable  VARCHAR2(255); 
    CurrentPollID NUMBER; 
    TableIDs  number_tab; 
    InstanceIDs  number_tab; 
    IDCount   BINARY_INTEGER; 
    PublisherLSN RAW(10); 

BEGIN 
    -- Put the published tableIDs in a PL/SQL table of IDs 
    HREPL.GetTableIDs(TableIDs, InstanceIDs); 

    -- Get the current Poll ID 
    SELECT Publisher_CurrentPollid INTO CurrentPollID FROM HREPL_Publisher; 

    IDCount := TableIDs.COUNT; 
    -- For each table represented in the ID list 
    FOR id_ind IN 1 .. IDCount 
    LOOP 

     LogTable := REPLACE(REPLACE(ArticleLogTemplate, MatchString, TO_CHAR(TableIDs(id_ind))), 
                 MatchStringY, TO_CHAR(InstanceIDs(id_ind))); 

     BEGIN 
      -- Generate command to delete from the article log those entries appearing in the 
      -- Poll Table with the current PollID 
      SQLCommand := 'DELETE FROM ' || LogTable || ' l ' || 
           'WHERE l.ROWID IN (SELECT chartorowid(p.Poll_ROWID) FROM HREPL_POLL p ' || 
           '    WHERE p.Poll_PollID = :Pollid)'; 

      HREPL.ExecuteCommandForPollID(SQLCommand, CurrentPollID); 

     EXCEPTION 
      WHEN OTHERS THEN NULL; 
     END; 
    END LOOP; 

    -- Delete from HREPL_Event those entries appearing in the Poll Table 
    -- with the current PollID. 
    DELETE FROM HREPL_Event e 
     WHERE ROWID in (SELECT chartorowid(p.Poll_ROWID) FROM HREPL_POLL p 
         WHERE p.Poll_PollID = CurrentPollID); 

     -- Delete entries from the Poll Table having the current Pollid 
    DELETE FROM HREPL_Poll 
     WHERE Poll_PollID = CurrentPollID; 

    -- Drop all views associated with articles that are marked as UnPublishPending. 
    -- Note: We cannot perform these drops in UnPublish table, since UnPublish 
    --  table can execute concurrently with PollBegin and the querying 
    --  of published tables by the log reader. PollEnd, however, executes 
    --  synchronously with respect to these activities, so can be used 
    --  to cleanup log tables and views that are no longer needed. 
    HREPL.CleanupLogsandViews; 

    -- Mark the last request as PollEnd, and update the Publisher LSN 
    -- to reflect the LSN committed at the publisher. 
    UPDATE HREPL_Publisher 
    SET Publisher_PollInProcess = NoPollInProcess, 
     Publisher_LSN = argLSN; 

    -- Commit transaction 
    COMMIT; 

EXCEPTION 
    WHEN OTHERS THEN 
     ROLLBACK; 
     RAISE; 

END PollEnd; 
+0

您可能已经注意到我已经删除并且多次删除了这个答案,但是现在我确信它可能会起作用......但是当然应该先在安全的环境中进行仔细的测试。 –