我本周末进行了数据迁移,并发现我无法获得DBA的帮助,因此缺乏SQL Server知识。所有其他DBA都是Oracle,不会触及SQL Server。我的安全性有限,我无法创建一个作业或SSIS包来处理这个问题。
我有一个脚本,我正在批量运行。在这个批处理中,我正在运行带有逻辑的存储过程。存储过程有表变量,我只是读到你无法将它们作为事务运行。有人可以看到这种整体方法,看看我是否遗漏了任何东西,或者我可以更有效地运行它? BigTable有大约25M的记录,所有索引,FK,约束都被删除。我打算暂时为这批次添加一些索引。它将运行大约5天。
Create Procedure ConvertStuff AS
BEGIN
declare @id uniqueIdentifier
declare @importdate DateTime
declare @Data varchar(max)
declare @tableX table
---
declare @tableY table
---
declare @tableZ table
---
SET NOCOUNT ON
select top 1 @ID = bt.ID, @Data = bt.RawData, @importDate = bt.ImportDate from Processed p with (NOLOCK)
Inner join BigTable bt with (NOLOCK) on p.ID = bt.ID where p.isProcessed = 0
while (not @ID is null)
Begin
BEGIN TRY
--Do stuff here
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage,
@ErrorSeverity,
@ErrorState
);
update bigTable set isProcessed = -1 where ID = @ID
break
END CATCH
select top 1 @ID = bt.ID, @Data = bt.RawData, @importDate = bt.ImportDate from Processed p with (NOLOCK)
Inner join BigTable bt with (NOLOCK) on p.ID = bt.ID where p.isProcessed = 0
END
--Do I need to drop the @ tables here? Should I convert these to # ?
END
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Running this....
-- This will be dropped once the migration is done
CREATE TABLE [Processed]
(
[ID] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[isProcessed] [bit] Default(0) NOT NULL,
)
CREATE NONCLUSTERED INDEX [idx_isProcessed] ON [Processed]
(
[isProcessed] ASC
)
GO
SET ROWCOUNT 25000
declare @msg varchar(50)
DECLARE @ErrorMessage NVARCHAR(4000)
DECLARE @ErrorSeverity INT
DECLARE @ErrorState INT
While (1=1)
BEGIN
BEGIN TRY
BEGIN TRANSACTION
Insert into [Processed] (ID, isProcessed)
Select ID, 0 from BigTable where recordUpdated = 0
exec ConvertStuff
IF @@ROWCOUNT = 0
BEGIN
Print @@ROWCOUNT
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
BREAK
END CATCH
END
drop table Processed
答案 0 :(得分:2)
这是在不查杀系统的情况下有效批量复制表的正确方法。仅当表在复制期间是只读时,此策略才有效。如果您的表格可以更改,则必须将其与其他策略配对,以便跟踪和更新已更改的记录。
批量复制方法将阻止您对表进行4天锁定,并允许您定期备份事务日志。如果您需要停止或失败,它还会阻止4天的回滚。
在发布之前运行此操作,然后在发布到表格上限期间再次运行。与往常一样,在尝试使用实时系统之前练习运行并停止脚本。
DECLARE @CurrentId UNIQUEIDENTIFIER,
@BatchSize INT;
SET @BatchSize = 50000;
SELECT TOP 1
@CurrentId = ID
FROM NewTable
ORDER BY ID DESC;
SELECT
@LastId = ID
FROM OldTable
ORDER BY ID DESC;
IF (@CurrentId IS NULL)
SET @CurrentId = '00000000-0000-0000-0000-000000000000';
PRINT 'Copying from ' + CONVERT(VARCHAR(40), @CurrentId) + ' to ' + CONVERT(VARCHAR(40), @LastId);
CREATE TABLE #Batch
(
ID UNIQUEIDENTIFIER
);
WHILE (@CurrentId < @LastId)
BEGIN
PRINT CONVERT(VARCHAR(40), @CurrentId);
TRUNCATE TABLE #Batch;
-- Get your new batch
INSERT INTO #Batch
SELECT TOP (@BatchSize)
*
FROM OldTable
WHERE ID > @CurrentId
ORDER BY ID;
-- I'd recommend being specific with columns, you might also need to turn on 'SET IDENTITY_INSERT <Table> ON'
INSERT INTO NewTable
SELECT *
FROM OldTable
INNER JOIN #Batch ON #Batch.ID = OldTable.ID
LEFT JOIN NewTable ON NewTable.ID = OldTable.ID
WHERE NewTable.ID IS NULL;
IF (@@ERROR <> 0)
BREAK
SELECT TOP 1
@CurrentId = ID
FROM #Batch
ORDER BY ID DESC;
END