不是 DBA 并且没有系统管理员权限来进行备份/恢复,以下是复制一组表的好解决方案吗?(我有一个链接服务器从serverA
到serverB
)
复制表
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[copyTables]
AS
-- NOCOUNT ON added to prevent extra result sets from interfering
-- with SELECT statements. XACT_ABORT ON to terminate the transaction
-- and rollback if a run-time error occurs.
SET NOCOUNT, XACT_ABORT ON
BEGIN
DECLARE @serverName varchar(50), @dbName varchar(50), @schemaName varchar(50)
SET @serverName = QUOTENAME('serverB')
SET @dbName = QUOTENAME('db')
SET @schemaName = QUOTENAME('dbo')
BEGIN TRY
BEGIN TRANSACTION
EXEC [dbo].[copyTable] @serverName, @dbName, @schemaName, 'tbl1', 'copyLog'
EXEC [dbo].[copyTable] @serverName, @dbName, @schemaName, 'tbl2', 'copyLog'
EXEC [dbo].[copyTable] @serverName, @dbName, @schemaName, 'tbl3', 'copyLog'
...
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- Insert error into log table
ROLLBACK
END CATCH
END
GO
复制表
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[copyTable]
@serverName varchar(50),
@dbName varchar(50),
@schemaName varchar(50),
@tableName varchar(50),
@logTableName varchar(50)
AS
-- NOCOUNT ON added to prevent extra result sets from interfering
-- with SELECT statements. XACT_ABORT ON to terminate the transaction
-- and rollback if a run-time error occurs.
SET NOCOUNT, XACT_ABORT ON
BEGIN
DECLARE @localFullName varchar(200), @localShortName varchar(150),
@foreignFullName varchar(200), @logShortName varchar(150);
SET @localFullName = QUOTENAME(@dbName) + '.' + QUOTENAME(@schemaName)
+ '.' + QUOTENAME(@tableName);
SET @localShortName = QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName);
SET @foreignFullName = QUOTENAME(@serverName) + '.' + QUOTENAME(@dbName)
+ '.' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName);
SET @logShortName = QUOTENAME(@logTableName) + '.' + QUOTENAME(@schemaName)
+ '.' + QUOTENAME(@tableName);
IF EXISTS
(
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(@localShortName)
AND type in (N'U')
)
BEGIN
DROP TABLE @localShortName;
SELECT *
INTO @localFullName
FROM @foreignFullName;
INSERT INTO @logShortName (stamp, [message])
VALUES
(
GETDATE(),
'Table ' + @foreignFullName + ' was copied'
);
END
END
这看起来是一个很好的工作解决方案。但是请记住,在一个事务中复制大量数据可能会显着增加您的日志文件。这会花费大量时间,并可能导致意外的驱动器空间短缺。此外,在此期间,外部连接完全无法访问目标表。源选项卡也可能被阻止,具体取决于您的事务隔离级别。
将实际数据移动分解为小批量可能会更好。但是如果发生并发写入,您将失去事务一致性。
正如 Aaron 所提到的,您可能还想研究现有的工具,例如 DataCompare(也不能保证事务的一致性)。如果您必须定期执行此复制过程,您还可以查看快照复制。(这将保证事务的一致性,但需要由系统管理员设置。但是,在初始设置之后,您可以自己开始同步。)
最后,如果你使用你的解决方案,请确保在错误情况下你首先回滚事务然后记录到错误日志表,否则你也会回滚那个新条目。您还应该检查错误发生时是否确实存在交易:
IF XACT_STATE() != 0 ROLLBACK