利用数据库复制技术 实现数据同步更新
复制的概念
复制是将一组数据从一个数据源拷贝到多个数据源的技术,是将一份数据发布到多个存储站点上的有效方式。使用复制技术,用户可以将一份数据发布到多台服务器上,从而使不同的服务器用户都可以在权限的许可的范围内共享这份数据。复制技术可以确保分布在不同地点的数据自动同步更新,从而保证数据的一致性。
SQL复制的基本元素包括
出版服务器、订阅服务器、分发服务器、出版物、文章
SQL复制的工作原理
SQL SERVER 主要采用出版物、订阅的方式来处理复制。源数据所在的服务器是出版服务器,负责发表数据。出版服务器把要发表的数据的所有改变情况的拷贝复制到分发服务器,分发服务器包含有一个分发数据库,可接收数据的所有改变,并保存这些改变,再把这些改变分发给订阅服务器
SQL SERVER复制技术类型
SQL SERVER提供了三种复制技术,分别是:
1、快照复制(呆会我们就使用这个)
2、事务复制
3、合并复制
只要把上面这些概念弄清楚了那么对复制也就有了一定的理解。接下来我们就一步一步来实现复制的步骤。
第一先来配置出版服务器
(1)选中指定[服务器]节点
(2)从[工具]下拉菜单的[复制]子菜单中选择[发布、订阅服务器和分发]命令
(3)系统弹出一个对话框点[下一步]然后看着提示一直操作到完成。
(4)当完成了出版服务器的设置以后系统会为该服务器的树形结构中添加一个复制监视器。同时也生成一个分发数据库(distribution)
第二创建出版物
(1)选中指定的服务器
(2)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令。此时系统会弹出一个对话框
(3)选择要创建出版物的数据库,然后单击[创建发布]
(4)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助) 
(5)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,SQLSERVER允许在不同的数据库如 ORACLE或ACCESS之间进行数据复制。但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器
(6)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表
(7)然后[下一步]直到操作完成。当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库。
第三设计订阅
(1)选中指定的订阅服务器
(2)从[工具]下拉菜单中选择[复制]子菜单的[请求订阅]
(3)按照单击[下一步]操作直到系统会提示检查SQL SERVER代理服务的运行状态,执行复制操作的前提条件是SQL SERVER代理服务必须已经启动。
(4)单击[完成]。完成订阅操作。
完成上面的步骤其实复制也就是成功了。但是如何来知道复制是否成功了呢?这里可以通过这种方法来快速看是否成功。展开出版服务器下面的复制——发布内容——右键发布内容——属性——击活——状态然后点立即运行代理程序接着点代理程序属性击活调度把调度设置为每一天发生,每一分钟,在0:00:00和23:59:59之间。接下来就是判断复制是否成功了打开C:\Program Files\Microsoft SQL Server\MSSQL\REPLDATA\unc\XIAOWANGZI_database_database下面看是不是有一些以时间做为文件名的文件夹差不多一分中就产生一个。要是你还不信的话就打开你的数据库看在订阅的服务器的指定订阅数据库下看是不是看到了你刚才所发布的表

解决方案 »

  1.   

    1.作发出版,分发服务器,必须要启动 SQLServerAgent服务
    订阅服务器可以不用启动 SQLServerAgent服务.2.在进行操作之前,必须在出版分发服务器这边注册订阅服务器,两边最好建有相同结构的数据库
    3.从菜单中选Tools>>Republication>>Configure Publishing And SubScripter ,接着进行配置,Configure Publishing ,Subscirpter And Distribution...配置要分发的数据库及其表,视图等4.创建分发管理 Create And Manager Publication,选择要分发的数据库5.接上在此基础上或Push Subscriptions to other,选取分发数据库下的出版物,再按右边的按钮:Push New Subscription,逐步按向导完成
      

  2.   

    解决两相同数据库数据同步的问题为用户组建一套SQL Server应用系统时,用户经常提到这样的要求:
     
      如果其中一台服务器坏了,怎样才能防止数据丢失,并在最短的时间内恢复系统?要解决这个问题,肯定需要两台服务器,并在两台服务器上装有相同的数据库,保持两台服务器中的数据同步,当主服务器坏了时,将另外一台服务器更改一下计算机名称,从而使得工作站可以继续运行.那么如何保持两台数据库中的数据同步呢? SQL Server提供了出版-定阅机制,可以将数据实时的拷贝到定阅服务器中. 但在实际应用中,发现一旦建立起了出版-定阅关系,在定阅服务器数据库中的触发器,主键等东西都不见了!!! 当主服务器不能正常工作时,要想让另一台服务器转变为主服务器,除更改计算机名外,还需建立触发器,索引等,过程比较烦琐.特别当用户对数据库维护不熟悉时,这种操作更加麻烦.Sql Server做为一种数据库管理系统,它与客户的接口都是通过SQL语句进行的, 用户在插入一条记录时,SQL Server会接收到Insert语句;更改一条记录时,会接收到 Update命令...
    那么如果我们能在SQL Server中跟踪到所有发给SQL Server的SQL语句,那么我们就可以知道数据库发生了哪些改变,并可以将这种改变发给另外一到服务器,从而实现数据实时同步的功能.值得高兴的是,SQL Server 提供了跟踪功能 ,它们是以 xp_trace_XXXXXX的一系列存储过程, 
    你可以设置过滤条件,从而只跟踪影响你的数据库 变化的SQL 语句,将这些SQL 语句存放在本地表中,再从本地表中读出,发送给另外一台服务器 ,从而实现数据同步功能. 这种方法可以跟踪任何类型的变化,包括Image类型数据的改变.以下面是用BCB5.0语句实现建立跟踪过程:
    bool TForm1 :: BuildTrace(int DBID,
                            AnsiString AppFilter,
                            AnsiString SQLFilter,
                            AnsiString DstTable,
                            int &TraceHandle)
    {
        char tempBuf[512];    Query1 -> Close();
        Query1 -> SQL -> Clear();
        TStrings *pSQL = Query1 -> SQL;
        pSQL -> Add("USE master");
        pSQL -> Add("DECLARE @queue_handle int");
        pSQL -> Add("DECLARE @column_value int");
        pSQL -> Add("SET @column_value = 67108864|1|512|1024|10384");
        pSQL -> Add("EXEC  xp_trace_addnewqueue 1000,5,95,90,@column_value,@queue_handle OUTPUT");
        pSQL -> Add("EXEC xp_trace_seteventclassrequired @queue_handle, 41,1 ");
       
        wsprintf(tempBuf,"EXEC xp_trace_setappfilter @queue_handle,'%s',NULL", AppFilter.c_str());
        pSQL -> Add(AnsiString(tempBuf));    wsprintf(tempBuf,"EXEC xp_trace_setdbidfilter @queue_handle,%d",DBID);
        pSQL -> Add( AnsiString(tempBuf));    wsprintf( tempBuf,"Exec xp_trace_settextfilter @queue_handle,'%s',NULL", SQLFilter.c_str());
        pSQL -> Add(AnsiString(tempBuf));         wsprintf( tempBuf,
                  "EXEC xp_trace_setqueuedestination @queue_handle,4,1,NULL,'%s'",
                  DstTable.c_str()
                );
        pSQL -> Add( AnsiString(tempBuf));    pSQL -> Add("EXEC xp_trace_startconsumer @queue_handle");
        pSQL -> Add("SELECT @queue_handle QueueHandle");    try
        {
            Query1 -> Open();
        }
        catch(...)
        {
            return false;
        }
        TraceHandle = Query1 -> FieldByName("QueueHandle") -> AsInteger;
        return true;
    }解决两相同数据库数据同步的问题 (续) 遇到了用户要求的提供双机热备份功能,
    最终的解决方案是:
     在主服器上运行同步程序(用BCB5.0编写的程序),同步程序在启动时,在SQL Server 中建立跟踪过程,跟踪过程将跟踪到的SQL 语句存放在主服务器的跟踪表中;
      同步程序每隔半分钟访问跟踪表,将其中的SQL 语句发送到备份服务器,并将其删除!
    /* 功能: 在SQL Server中建立跟踪
      输入参数: DBID  - 想要跟踪的数据库的ID号,可以用数据库名在      master.dbosysdatabases中查出。
               AppFilter - 限制跟踪哪个客户端应用程序提交给SQL Server的SQL语句
               SQLFilter - 限制跟踪哪类的SQL 语句,可以控制只跟踪UPDATE,INSERT,DELETE 语句
               DstTable - 将跟踪到的信息存储到数据库的哪一个表中
               TraceHandle -引用类型变量,返回给调用者建立起的跟踪句柄
      返回值: true 成功,false 失败
    */bool TForm1 :: BuildTrace(int DBID,
                            AnsiString AppFilter,
                            AnsiString SQLFilter,
                            AnsiString DstTable,
                            int &TraceHandle)
    {
        char tempBuf[512];                 Query1 -> Close();            //Query1 为 TADOQuery的组件
                                  //实验中发现若用BDE中的TQuery组件,对跟踪到的  
                                  //Image类型数据会操作时会发生错误.
        Query1 -> SQL -> Clear();
        TStrings *pSQL = Query1 -> SQL;    
        pSQL -> Add("USE master");   //将当前数据库设为master        
        pSQL -> Add("DECLARE @queue_handle int");   
        pSQL -> Add("DECLARE @column_value int");
           // 可以跟踪很多种信息,但通常只需要其中一部分, @column_value用来确定需要哪些信息.
        //下行每个数字代表一列,具体可参见Transact -SQL Help
        pSQL -> Add("SET @column_value = 67108864|1|512|1024|10384");
          
           // 加入一个跟踪过程,若成功, @queue_handle将是一个有效的值 
        pSQL -> Add("EXEC  xp_trace_addnewqueue 1000,5,95,90,@column_value,@queue_handle OUTPUT");
        
       // 以下句设置跟踪条件
       //设置跟踪何种事件, 41为TSQL Complete事件, 还有其它事件,如连接事件等等,
       // 但对同步功能来说,只需要TSQL Complete事件.
        pSQL -> Add("EXEC xp_trace_seteventclassrequired @queue_handle, 41,1 ");
       
       //设置跟踪哪种客户端的发过来的SQL 语句,客户端在向SQL Server发出命令时,都有一个
     // Application Name
        wsprintf(tempBuf,"EXEC xp_trace_setappfilter @queue_handle,'%s',NULL", AppFilter.c_str());
        pSQL -> Add(AnsiString(tempBuf));
       
        // 设置跟踪针对哪个数据库的SQL 语句
        wsprintf(tempBuf,"EXEC xp_trace_setdbidfilter @queue_handle,%d",DBID);
        pSQL -> Add( AnsiString(tempBuf));  //设置SQL 语句的过滤条件,可设置成" UPDATE%;DELETE%;INSERT%",则只跟踪UPDATE
      // INSERT 和 DELETE语句
        wsprintf( tempBuf,"Exec xp_trace_settextfilter @queue_handle,'%s',NULL", SQLFilter.c_str());
        pSQL -> Add(AnsiString(tempBuf));   //设置将跟踪到的信息存放在哪个表里 ,
       //如果表不存在,则自动创建,表的列数由前面的@colomun_value控制.
       // 为以后方便读出控制,可以在自动创建了这个表后,手工的为其加上ID字段(自动增长字段),
      // 并做为主索引.    wsprintf( tempBuf,
                  "EXEC xp_trace_setqueuedestination @queue_handle,4,1,NULL,'%s'",
                  DstTable.c_str()
                );
        pSQL -> Add( AnsiString(tempBuf));     // 开始跟踪
        pSQL -> Add("EXEC xp_trace_startconsumer @queue_handle");
        pSQL -> Add("SELECT @queue_handle QueueHandle");    
         // 将批命令提交到SQL SERVER, 执行完毕后,跟踪过程就建立起来了
           
        try
        {
            Query1 -> Open();
        }
        catch(...)
        {
            return false;
        }
        TraceHandle = Query1 -> FieldByName("QueueHandle") -> AsInteger;
        return true;
    }//调用过程
    ...
    int TraceHandle
    int DBID;DBID = GetDBID("MyDB1");    //根据数据库名从SQL Server的sysdatabases中查询DBIDif( BuildTrace( DBID,
                        "MyApp",
                         "INSERT%;UPDATE%;DELETE%",
                         "MyDB1.dbo.MyTrace")
       == true)
    {
        Application -> MessageBox("跟踪过程已被建立","提示",MB_OK);
    }
    else
    {
     Application -> MessageBox("跟踪过程建立失败","提示",MB_OK);
    }