我有一些同步过程使用“LastUpdate”标志来更新自上次同步尝试以来更改的任何记录。SQL合并,表值参数和GetDate()
稍后我更新了代码以利用表值参数,而不是一次同步(添加/更新)一行。这是更快的10倍或更多。
但是,我现在遇到了一个竞赛条件,有时会导致更新被错过。我赶紧张罗了一些SQL脚本来测试我的情况/理论(任何大表ID将工作):
/*CREATE TYPE IntTable AS TABLE(
[RequestID] [int] NOT NULL
)
GO
CREATE TABLE MergeTest(
[ID] [int] IDENTITY(1,1) NOT NULL,
[RequestID] [int] NOT NULL,
[PreDate] [datetime] NOT NULL,
[MergeDate] [datetime] NOT NULL
GO
*/
DECLARE @requestIDs As IntTable
INSERT INTO @requestIDs
SELECT RequestID FROM Request
DECLARE @preDate As DateTime = Getdate()
MERGE INTO MergeTest USING @requestIDs SRC
ON MergeTest.RequestID = SRC.RequestID
WHEN MATCHED THEN
UPDATE SET PreDate = @preDate, MergeDate = GetDate()
WHEN NOT MATCHED THEN
INSERT (RequestID, PreDate, MergeDate)
VALUES (SRC.RequestID, @preDate, GetDate());
SELECT TOP 100 * FROM MergeTest
示例结果
ID RequestID PreDate MergeDate
1 169880 2016-05-13 13:57:54.643 2016-05-13 13:57:54.643
所以,你可以看到MergeDate(GETDATE( ))来自何时合并开始,而不是何时结束。
比赛条件可以是这样的:
Check what has been updated since 14:59
Start a merge at 15:00
Check what has been updated since 15:00
Merge completes, but with a LastUpdate of 15:00
Check what has been updated since 15:01
所有从合并的记录将被跳过。事实上,这种竞争状态很少发生,因为我们正在说毫秒而不是几分钟,但它确实发生了。
问题是...没有运行第二个脚本来重新更新LastUpdate与合并后的日期,有没有什么办法让合并语句使用它完成工作的日期而不是当它开始了吗?