事务复制的注意事项
对于事务复制有若干注意事项:
事务日志空间。
分发数据库的磁盘空间。
每个已发布表的主键。
触发器。
大型对象 (LOB) 数据类型。
可更新订阅(如果使用这些订阅)。 有关可更新订阅注意事项的详细信息,请参阅事务复制的可更新订阅。
事务日志空间
对于要使用事务复制发布的每个数据库,请确保已为事务日志分配了足够的空间。 已发布数据库的事务日志可能要比相同的未发布数据库的日志需要更大的空间,因为日志记录被移至分发数据库之后才会被截断。
如果分发数据库不可用,或者日志读取器代理没有运行,则发布数据库的事务日志将继续增长。 日志不能在超过尚未传递至分发数据库的最早的已发布事务处截断。 建议将事务日志文件设置为自动增长,以便日志可以适应这些情况。 有关详细信息,请参阅 CREATE DATABASE (Transact-SQL) 和 ALTER DATABASE (Transact-SQL)。
建议在分发数据库上设置 sync with backup 选项,该选项可以推迟发布数据库上日志的截断,直到分发数据库中的相应事务均已备份为止。 这可导致发布数据库中产生更大的事务日志。 有关此选项的详细信息,请参阅快照复制和事务复制的备份和还原策略。
分发数据库的磁盘空间
请确保具有足够的磁盘空间存储分发数据库中复制的事务:
如果不能使订阅服务器立即使用快照文件(这是默认设置):事务将一直存储,直到将其复制到所有订阅服务器,或直到保持期结束为止(两者中取时间较短者)。
如果创建事务发布,并使订阅服务器可立即使用快照文件:事务将一直存储,直到将其复制到所有订阅服务器,或直到快照代理运行并创建了新的快照为止(两者中取时间较长者)。如果快照代理两次运行的时间间隔大于发布的最大分发保持期(默认为 72 小时),则超过保持期的事务将从分发数据库中删除。 有关详细信息,请参阅订阅过期和停用。
虽然使快照能够立即为订阅服务器所用可以提高新订阅服务器访问发布的速度,但此选项会增加分发数据库存储所需的磁盘空间。 这还意味着每次快照代理运行时,都将生成一个新的快照。 如果不使用此选项,则仅当存在新订阅时才会生成新快照。
触发器
在订阅数据库上使用触发器时,应了解下列事项:
默认情况下,触发器将在 XACT_ABORT 设置为 ON 的情况下执行。 当分发代理正在对订阅服务器应用更改时,如果触发器中的某个语句导致错误,则整批更改都将失败,而不只是单个语句。 在事务复制中,可以使用分发代理的 -SkipErrors 参数来跳过导致错误的语句。 如果在 XACT_ABORT 为 ON 的情况下使用 -SkipErrors,那么,如果某个语句导致错误,则会跳过整批更改。 如果使用了 -SkipErrors 参数,除非需要在触发器中将 XACT_ABORT 设置为 ON,否则,建议将其设置为 OFF。 若要将该选项设置为 OFF,请在触发器定义中指定 SET XACT_ABORT OFF。 有关 XACT_ABORT 的详细信息,请参阅 SET XACT_ABORT (Transact-SQL)。 有关 -SkipErrors 参数的详细信息,请参阅跳过事务复制中的错误。
建议不要在订阅服务器的触发器中包含显式事务。 事务复制使用事务批处理来减少网络的往返次数,从而提高性能。 如果将包含 ROLLBACK 语句的触发器添加到订阅服务器,则事务批处理可能会取消,并可能引发服务器错误 266。(EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。 上一计数 = %ld,当前计数 = %ld。) 批处理可能包含来自多个事务的命令,也可能是发布服务器中某个大事务的一部分,因此回滚事务会危及事务的完整性。
如果确实要包含显式事务,请确保触发器中的所有 COMMIT 语句都具有相应的 BEGIN TRANSACTION 语句。 如果 COMMIT 不具有相应的 BEGIN TRANSACTION,则会导致对订阅服务器进行非事务应用行更改。 此外,如果分发代理遇到服务器错误 266 而尝试回滚事务或批处理命令以便再次应用时,会再次失败。 当代理尝试应用已应用的命令时,会导致重复键失败。
有关触发器的详细信息,请参阅使用 NOT FOR REPLICATION 来控制约束、标识和触发器。
大型对象 (LOB) 数据类型
事务复制支持发布 LOB,并可对 LOB 列执行部分更新:如果 LOB 列进行了更新,则只是复制已更改的数据段,而不是复制列中的所有数据。
如果已发布的表中包含任何 LOB,则请考虑使用下列分发代理参数:-UseOledbStreaming、-OledbStreamThreshold 和 -PacketSize。设置这些参数的最直接的方法是使用题为“用于 OLEDB 流式处理的分发配置文件”的分发代理配置文件。 有关详细信息,请参阅复制代理配置文件。 除了此预定义的配置文件之外,还可以在创建或修改的代理配置文件中,或在命令行中,指定该参数。 有关详细信息,请参阅:
text、ntext 和 image 数据类型
在事务发布中复制 text、ntext 和 image 数据类型的过程有若干需要注意的事项: 建议使用 varchar(max)、nvarchar(max) 和 varbinary(max) 数据类型,而不要使用分别与他们对应的 text、ntext 和 image 数据类型。
如果确实要使用 text、ntext 或 image,注意下列事项:
WRITETEXT 和 UPDATETEXT 语句应包含在显式事务中。
在已发布表中,可以用带 WITH LOG 选项的 WRITETEXT 和 UPDATETEXT 语句来复制日志中记录的文本操作。 由于事务复制在事务日志中跟踪更改,因此需要使用 WITH LOG 选项。
只有所有订阅服务器都运行 SQL Server 时才可以使用 UPDATETEXT 操作。 WRITETEXT 操作作为 UPDATE 语句复制,因此它们还可以用于非 SQL Server 的订阅服务器。
可配置参数 max text repl size 控制着可复制的 text、ntext、varchar(max)、nvarchar(max) 和 image 数据的最大大小(字节)。 这样便可支持: ODBC 驱动程序和 OLE DB 访问接口;无法处理上述数据类型的较大值的 SQL Server 数据库引擎 实例;以及具有系统资源(虚拟内存)约束的分发服务器。 当具有上述数据类型之一的列已发布,并且已运行超过配置限制的 INSERT、UPDATE、WRITETEXT 或 UPDATETEXT 操作时,操作将失败。
使用 sp_configure (Transact-SQL) 系统存储过程可以设置 max text repl size 参数。
当发布 text、ntext 和 image 列时,文本指针应在 UPDATETEXT 操作或 WRITETEXT 操作的事务内检索(并可重复读取)。 例如,不要在一个事务中检索文本指针,然后在另一个事务中使用它。 它可能已经移动并失效。
另外,在获得文本指针后,不应在执行 UPDATETEXT 或 WRITETEXT 语句之前,执行任何可能改变文本指针所指向文本位置的操作(如更新主键)。
以下是使用 UPDATETEXT 和 WRITETEXT 操作处理要复制的数据的建议方法:
开始事务。
使用带有 REPEATABLE READ 隔离级别的 TEXTPTR() 获取文本指针。
在 UPDATETEXT 或 WRITETEXT 操作中使用文本指针。
提交事务。
注意 如果未在同一事务中获取文本指针,则允许在发布服务器进行修改,但更改不会发布到订阅服务器。
例如:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN DECLARE @mytextptr varbinary(16) SELECT @mytextptr = textptr(Notes) FROM Employees WHERE EmployeeID = '7' IF @mytextptr IS NOT NULL BEGIN UPDATETEXT Employees.Notes @mytextptr 0 NULL 'Terrific job this review period.' -- Dummy update to fire trigger that will update metadata and ensure the update gets propagated to other Subscribers. UPDATE Employees -- Set value equal to itself. SET Notes = Notes WHERE EmployeeID = '7' END COMMIT TRAN SET TRANSACTION ISOLATION LEVEL READ COMMITTED
注意 |
---|
此示例基于 Northwind 数据库,默认情况下不安装此数据库。 有关安装此数据库的信息,请参阅 Microsoft 下载中心中的 Northwind and pubs Sample Databases(Northwind 和 pubs 示例数据库)。 |
调整订阅服务器数据库的大小时需要注意:所复制的 text、ntext 和 image 列的文本指针必须在订阅服务器的表上初始化,即使它们在发布服务器中未初始化也应如此。 因此,即使分发任务向订阅服务器表中添加的各个 text、ntext 和 image 列的内容为空,它们至少也要各自占用 43 字节的数据库存储空间。