服务器 频道

解决两相同数据库数据同步的问题

  【IT168 服务器学院】为用户组建一套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(Ans

  在上一篇<<解决两相同数据库数据同步的问题>> ,由于时间关系,没有对BuildTrace函数给出说明,在此做以补充 .

  笔者是在山东潍坊出差时,遇到了用户要求的提供双机热备份功能,
  最终的解决方案是:
  在主服器上运行同步程序(用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()

0
相关文章