在上一篇<<解决两相同数据库数据同步的问题>> ,由于时间关系,没有对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() ); 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中查询DBID
if( BuildTrace( DBID, "MyApp", "INSERT%;UPDATE%;DELETE%", "MyDB1.dbo.MyTrace") == true) { Application -> MessageBox("跟踪过程已被建立","提示",MB_OK); } else { Application -> MessageBox("跟踪过程建立失败","提示",MB_OK); } ....

|