事务复制是数据同步中常用的一种手段,复制过程难免会遇到不少问题,就笔者遇到的问题而言,一般有两大类:一类是通过重新启动Distributor Agent即可解决的问题,另一类是因为Subscriber修改了数据,导致发布的数据有冲突,这类问题一般需要手工去修复。
TableDiff是SQL Server 2005的一个命令行实用工具,该工具可以比较两个表,并且生成数据同步的脚本。借助这个工具,可以很容易地修复两个表数据不一致的问题。
但如果应用该工具来解决事务复制中数据冲突的问题,则除了同步数据外,还必须解决手工同步数据后,跳过未发布的错误事务序列的问题。
本文的第1部分介绍了TableDiff工具的用法和笔者的一些使用测试,第2部分介绍了如何借助这个工具来修复事务复制中的数据冲突问题。希望通过这两个部分的介绍,能让大家对于解决事务复制中的问题有所帮助。
比较两个非收敛的表中的数据,可以从命令提示符或在批处理文件中使用该实用工具执行以下任务:
Ø 在充当复制发布服务器的SQL Server实例中的源表与充当复制订阅服务器的一个或多个SQL Server实例中的目标表之间进行逐行比较。
Ø 通过只比较行数和架构可以执行快速比较。
Ø 执行列级比较。
Ø 生成T-SQL脚本,用以修复目标服务器中的差异,以使源表和目标表实现收敛。
Ø 将结果记录到输出文件或目标数据库的表中
使用该工具,需要满足下述条件:
Ø 只能用于SQL Server。
Ø 表中不包含sql_variant 数据类型的列
Ø Source Table和Destination Table需要满足下列一致性:
n 数目一致
n 名称一致
n 如果使用 -strict 选项,要求列的类型一致,否则,仅要求列的类型兼容。下面的数据类型是兼容的
源数据类型 | 目标数据类型 | 源数据类型 | 目标数据类型 |
tinyint | smallint、int、bigint | nvarchar(max) | ntext |
smallint | Int、bigint | varbinary(max) | image |
int | bigint | text | varchar(max) |
timestamp | varbinary | ntext | nvarchar(max) |
varchar(max) | text | image | varbinary(max) |
Ø Source Table必须至少包含一个:
n 主键
n 标识
n ROWGUID 列
n UNIQUE列
n 使用 -strict 选项时,Destination Table也必须至少包含一个上述列
Ø 如果生成T-SQL脚本,则脚本中不包含下列数据类型的列:
n varchar(max)
n nvarchar(max)
n varbinary(max)
n text
n ntext
n image
n timestamp
n xml
下表说明TableDiff的使用语法及相关的参数说明
TableDiff语法 | 参数说明 |
[ -? ] | { -sourceserver source_server_name[instance_name] -sourcedatabase source_database -sourcetable source_table_name [ -sourceschema source_schema_name ] [ -sourcepassword source_password ] [ -sourceuser source_login ] [ -sourcelocked ] -destinationserver destination_server_name[instance_name] -destinationdatabase subscription_database -destinationtable destination_table [ -destinationschema destination_schema_name ] [ -destinationpassword destination_password ] [ -destinationuser destination_login ] [ -destinationlocked ] [ -q ] [ -c ] [ -strict ] [ -b large_object_bytes ] [ -bf number_of_statements ] [ -f [ file_name ] ] [ -o output_file_name ] [ -et table_name ] [ -dt ] [ -rc number_of_retries ] [ -ri retry_interval ] [ -t connection_timeouts ] } | 返回支持参数的列表 |
|
设置Source信息。 如果未指定sourceuser,表示使用Windows身份验证。 Sourcelocked指定比较过程中锁定源表的方式,可以是TABLOCK或者HOLDLOCK, 未指定,则不锁定源表(NOLOCK) |
设置Destination信息。 如果未指定destinationuser,表示使用Windows身份验证。 destinationlocked指定比较过程中锁定目的表的方式,可以是TABLOCK或者HOLDLOCK, 未指定,则不锁定目的表(NOLOCK) |
比较方式: -q 只比较行数和架构 -c 比较列级差异,如果生成T-SQL脚本文件,则无论是否指定这个选项,都会进行列级差异比较 -strict 对源架构和目标架构进行严格比较 |
要比较的大型对象数据类型列的字节数,默认只比较前8000字节 |
生成T-SQL脚本的选项 -f 指定T-SQL脚本文件名 - bf 指定每个T-SQL脚本文件最多允许的语句数,超过此值会生成新脚本文件 |
输出文件的完整名称和路径 |
输出结果表 -et 指定输出结果表名(位于Subscriber) 如果结果表已经存在,则还需要指定-dt参数 |
指定连接相关的信息 -rc 指定失败重试的次数 -ri 指定重试的时间间隔 -t 指定连接超时时间 |
|
TableDiff的参数较长,根据使用的需求,下面的脚本可以帮助快速构建TableDiff命令。
DECLARE
@User sysname, @Pwd sysname, @lock sysname,
@Source nvarchar(1000), @Destination nvarchar(1000)
-- set parameters on here
SELECT
@User = '',
@lock = 'HOLDLOCK',
@Source = N'publisher.pubs..titles',
@Destination = N'subscriber.pubs..titles'
SELECT 'tablediff'
+ ' /sourceserver' + QUOTENAME(sSrv, '"')
+ ' /sourcedatabase' + QUOTENAME(sDb, '"')
+ ' /sourceschema' + QUOTENAME(sSch, '"')
+ ' /sourcetable' + QUOTENAME(sTb, '"')
+ CASE
WHEN @lock IS NULL OR @lock = '' THEN ''
ELSE ' /sourcelocked' + QUOTENAME(@lock, '"') END
+ CASE
WHEN @User IS NULL OR @User = '' THEN ''
ELSE ' /sourceuser' + QUOTENAME(@User, '"')
+ ' /sourcepassword' + QUOTENAME(@Pwd, '"')
END
+ ' /destinationserver' + QUOTENAME(dSrv, '"')
+ ' /destinationdatabase' + QUOTENAME(dDb, '"')
+ ' /destinationschema' + QUOTENAME(dSch, '"')
+ ' /destinationtable' + QUOTENAME(dTb, '"')
+ CASE
WHEN @lock IS NULL OR @lock = '' THEN ''
ELSE ' /destinationlocked' + QUOTENAME(@lock, '"') END
+ CASE
WHEN @User IS NULL OR @User = '' THEN ''
ELSE ' /destinationuser' + QUOTENAME(@User, '"')
+ ' /destinationpassword' + QUOTENAME(@Pwd, '"')
END
-- + ' /q'
-- + ' /c'
-- + ' /strict'
-- + ' /b"8000"'
-- + ' /bf"10000"'
-- + ' /f"c:syn.sql"'
-- + ' /o"c:output.txt"'
-- + ' /et"TableDiffResult"'
-- + ' /dt'
-- + ' /rc"3"'
-- + ' /ri"300"'
-- + ' /t"15"'
FROM(
SELECT
sSrv = ISNULL(PARSENAME(Source, 4), N'localhost'),
sDb = ISNULL(PARSENAME(Source, 3), N'master'),
sSch = ISNULL(PARSENAME(Source, 2), N'dbo'),
sTb = ISNULL(PARSENAME(Source, 1), N'notable'),
dSrv = ISNULL(PARSENAME(Destination, 4), N'localhost'),
dDb = ISNULL(PARSENAME(Destination, 3), N'master'),
dSch = ISNULL(PARSENAME(Destination, 2), N'dbo'),
dTb = ISNULL(PARSENAME(Destination, 1), N'notable')
FROM(
SELECT
Source = @Source, Destination = @Destination
)A
)A
对TableDiff的测试及测试结果如下。
能正确的生成同步Destination Table的脚本,通过执行该脚本,能够使Destination Table和Source Table的数据保持一致。
工具能报告Destination Table和Source Table结构有差异,但无法列出差异的明细,也无法生成结构差异修正的脚本。
如果使用/q选项进行测试,则工具能报告Destination Table和Source Table的记录数以及是否有差异,但无法生成同步Destination Table的脚本。
无论Table是否位于Replication中,只要TableDiff对表的要求,这些表都可以用TableDiff进行处理
经
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8591181/viewspace-891979/
,如需转载,请注明出处,否则将追究法律责任。