zoukankan      html  css  js  c++  java
  • MSSQL复制分发对异构数据库之间大容量数据分发造成异常

      由于历史遗留的问题,现有的架构中存在采用MSSQL的复制分发功能,从Oracle发布数据到MSSQL。

      关于这项发布的实现原理,官方表述如下:

      Oracle 事务发布是通过使用 SQL Server 的事务发布体系结构来实现的;但更改却是通过结合使用 Oracle 数据库上的数据库触发器和日志读取器代理来跟踪的。Oracle 事务发布的订阅服务器使用快照复制自动进行初始化;在以后发生更改时,将通过日志读取器代理对这些更改进行跟踪,并将更改传递到订阅服务器。

      创建 Oracle 发布时,将为 Oracle 数据库中所有已发布的表创建触发器和跟踪表。对发布的表进行数据更改时,将激发这些表的数据库触发器,并在复制跟踪表中为修改的每一行插入信息。然后,SQL Server 分发服务器上的日志读取器代理将数据更改信息从跟踪表移动到分发服务器上的分发数据库中。最后,与在标准事务复制中一样,分发代理将更改从分发服务器移动到订阅服务器。

      详细内容,请点击查看

      需要注意的是:

      1、大型对象 (LOB) 数据并不存储在项目日志表中,LOB 数据的更新始终是从已发布的表中直接检索的。 只有当影响 LOB 的操作激发了复制的表上的复制触发器时,才会在事务性发布中复制更新。 插入或删除包含 LOB 的行时,将激发 Oracle 触发器;但更新 LOB 列并不会激发触发器。 只有在同一 Oracle 事务中同时更新同一行的 LOB 列和非 LOB 列时,才会立即复制 LOB 列的更新。 否则,只有在下一次更新该行中的非 LOB 列时,才会刷新订阅服务器中的 LOB 列。 请确保您的应用程序可以接受此行为。

      2、在 MicrosoftSQL Server 分发服务器上安装 Oracle 客户端软件和 OLE DB 访问接口,然后重新启动 SQL Server 实例。如果分发服务器运行在 64 位平台上,则必须使用 64 位版本的 Oracle OLE DB 访问接口。

      3、在发布服务器上创建的各种表所代表的含义

    对象名

    对象类型

    说明

    HREPL_ArticleNlog_V

    更改跟踪表,当对已发布的表中进行了更改时,可使用此表存储更改信息。 为每个已发布的表创建一个更改跟踪表。

    HREPL_Changes

    Xactset 作业内部用来确定等待分配给事务集的更改数量的表。 有关此作业的详细信息,请参阅Oracle 发布服务器性能优化

    HREPL_Distributor

    分发服务器状态表,用于维护与 Oracle 发布服务器相关联的 SQL Server 分发服务器的信息。

    HREPL_Event

    事件表,用于同步快照和行计数请求。

    HREPL_Mutex

    用于确保 Oracle 包过程 PopulatePollTable 未由日志读取器代理和数据库作业并发执行的表。

    HREPL_Poll

    用于标识与几组已发布表的更改相关联的日志表项的表。

    HREPL_PublishedTables

    包含事务性发布中每个项目项的表。

    HREPL_Publisher

    发布服务器状态表,用于维护发布服务器的特定信息。

    HREPL_SchemaFilter

    包含在通过新建发布向导发布时不显示的架构的表。

    HREPL_XactsetCreateTimes

    标识与每个事务集相关联的创建时间的表。

    HREPL_XactsetJob

    包含用于 Xactset 作业的当前参数设置的表。

    HREPL_Pollid

    序列

    用于生成轮询 ID 的序列。

    HREPL_Seq

    序列

    用于对更改命令进行排序的序列。

    HREPL_Stmt

    序列

    用于生成语句 ID 的序列。

    HREPL

    包和包正文

    在发布服务器上创建的发布服务器支持代码的包。

    MSSQLSERVERDISTRIBUTOR

    公共同义词

    HREPL_Distributor 表的公共同义词。 如果将分发服务器配置为与 Oracle 发布服务器一起使用,而且此同义词已存在于数据库中,则应将其删除并重新创建。

    用 CASCADE 选项删除公共同义词和已配置的 Oracle 复制用户会删除 Oracle 发布服务器中的所有复制对象。

    HREPL_Len_I_J_K

    函数

    在 Oracle 发布包代码之外定义的、用于查询 LONG 列的长度(在为带有已发布 LONG 列的表生成参数化命令时使用)的函数。 为每个带有 LONG 列的已发布表创建一个函数。

    HREPL_DropPublisher

    过程

    在 Oracle 发布包代码之外定义的、用于删除 Oracle 发布服务器的过程。

    HREPL_ExecuteCommand

    过程

    在 Oracle 发布包代码之外定义的、用于在发布服务器上执行命令的过程。

    HREPL_ArticleN_Trigger_Row

    触发器

    为每个已发布表生成的、用于跟踪行更改的触发器。

    HREPL_ArticleN_Trigger_Stmt

    触发器

    为每个已发布表生成的、用于跟踪语句级更改的触发器。

    HREPL_Article_I_J

    视图

    为每个已发布表创建的、用于查询已发布表的视图。

    HREPL_Log_I_J_K

    视图

    为每个已发布表创建的、用于查询更改跟踪表的视图。

      遇到的问题: 

      当在发布服务器上更新了超过100万行的记录时,就会导致这台发布服务器上的所有项目都会出错。 据我在处理过程中的总结,估计是代理服务器无法读取这么大量的数据,或者是因为读取这么大量的数据,导致超时。 

      处理方法: 

      步骤一、先到复制监视器找到此发布服务器下的代理,停止“日志读取器代理”。若是停止之后,就直接重新启动,会一直显示初始化,最后的结果还是初始化不能成功。 

      步骤二、到Oracle发布服务器上找到元凶

    --动态生成拼接语句
    SELECT 'SELECT ''' || OBJECT_NAME || ''' TABLE_NAME ,   COUNT(1) CNT FROM PUB.' || OBJECT_NAME || ' UNION'
    FROM dba_objects 
    WHERE owner = 'PUB'  AND OBJECT_TYPE = 'TABLE' AND OBJECT_NAME LIKE '%ARTICLE%' OR OBJECT_NAME LIKE '%HREPL_POLL%'; 
    
    --对拼接结果进行查询
    SELECT * 
    FROM (
        SELECT 'HREPL_ARTICLE29LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE29LOG_1 UNION
        SELECT 'HREPL_ARTICLE28LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE28LOG_1 UNION
        SELECT 'HREPL_ARTICLE19LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE19LOG_1 UNION
        SELECT 'HREPL_ARTICLE21LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE21LOG_1 UNION
        SELECT 'HREPL_ARTICLE22LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE22LOG_1 UNION
        SELECT 'HREPL_ARTICLE23LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE23LOG_1 UNION
        SELECT 'HREPL_ARTICLE24LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE24LOG_1 UNION
        SELECT 'HREPL_ARTICLE25LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE25LOG_1 UNION
        SELECT 'HREPL_POLL' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_POLL UNION
        SELECT 'HREPL_ARTICLE39LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE39LOG_1 UNION
        SELECT 'HREPL_ARTICLE45LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE45LOG_1 UNION
        SELECT 'HREPL_ARTICLE43LOG_1' TABLE_NAME ,   COUNT(1) CNT FROM PUB.HREPL_ARTICLE43LOG_1 
    ) 
    ORDER BY CNT DESC ;

      步骤三:把表名包含“ARTICLE数字LOG”且行记录超过100W行的表清空(例如:我这次处理的就是“HREPL_ARTICLE45LOG”);

         特别说明:这样做是无奈之举,为了挽救在此发布服务器上的其他项目,把损失降低到最低。这样做,会造成包含清空表所依赖的的发布和订阅两边的数据不一致,最后可能还是需要重新初始化此发布项目。

    --查看发布的原表
    SELECT D1.owner
         , D1.name
         , D1.type
         , D1.referenced_owner
         , D1.referenced_name
         , D2.referenced_owner
         , D2.referenced_name
    FROM DBA_DEPENDENCIES D1
         JOIN DBA_DEPENDENCIES D2 ON D1.owner = D2.owner AND D1.name = D2.name
    WHERE  D1.REFERENCED_NAME = 'HREPL_ARTICLE45LOG_1' 
        AND D1.TYPE = 'TRIGGER' 
        AND D1.REFERENCED_OWNER <> D2.REFERENCED_OWNER 
        AND D2.REFERENCED_OWNER NOT IN ('SYS','PUBLIC') ; 
    
    --清空数据
    TRUNCATE TABLE mbs7_pub.HREPL_ARTICLE45LOG_1 ; 
    
    --把情况表对应的poll内的记录也清空
    DELETE FROM mbs7_pub.HREPL_POLL WHERE poll_tableid = 45 ;  --这里的tableid是和上面语句的“ARTICAL”后面的数字对应的

      步骤四、重新启动MSSQL复制监视器中的“日志读取器代理”。

        注:此时可以看到复制分发是正常的,但是,如上文所有,这样做在某个时候导致数据不一致,相当于埋了一个定时炸弹。所以,要在一个相对空闲的时间,把这个项目重新初始化一次,保证数据的一致性。

      更稳妥的解决是:

        尽量把大事务拆分一下,保证每次的操作记录少于100万,建议设置得更低一点。

      以上,如有纰漏,请不吝指正,若有更好的建议,请不吝指教。

  • 相关阅读:
    PCB设计实战项目指导班26层板的设计
    AT2171 [AGC007D] Shik and Game 题解
    UVA11327 Enumerating Rational Numbers 题解
    P6222 「P6156 简单题」加强版 题解
    CF702F TShirts 题解
    P3747 [六省联考 2017] 相逢是问候 题解
    『学习笔记』PollardRho 算法 题解
    P7453 [THUSCH2017] 大魔法师 题解
    CF1575L Longest Array Deconstruction 题解
    最大公约数之和
  • 原文地址:https://www.cnblogs.com/cnzeno/p/6277542.html
Copyright © 2011-2022 走看看