【发布时间】:2019-01-18 06:21:11
【问题描述】:
不乏涵盖此函数的主题和错误“为过程或函数 cdc.fn_cdc_get_all_changes 提供的参数数量不足”。我已经检查了其中的大部分,但无法找出问题所在。
这里的问题是我什至无法重现这个。它只是每天或两天随机出现几次,然后在几秒钟内消失,所以通常我只能在作业历史记录中将其视为失败的运行。
我浏览过的所有来源都说它通常来自使用该函数从捕获实例没有数据的时间范围内获取数据。但正如下面的代码将向您展示的那样,在运行函数之前,只检查这些值是否存在这些类型的异常。
DECLARE @END_LSN BINARY(10), @MIN_TABLE_LSN BINARY(10);
SELECT @END_LSN = sys.fn_cdc_get_max_lsn();
SELECT @MIN_TABLE_LSN = MAX(__$start_lsn) FROM MY_AUDIT_TABLE
IF @MIN_TABLE_LSN IS NOT NULL
SELECT @MIN_TABLE_LSN = sys.fn_cdc_increment_lsn(@MIN_TABLE_LSN)
ELSE
SELECT @MIN_TABLE_LSN = sys.fn_cdc_get_min_lsn('dbo_MY_AUDIT_TABLE')
IF @MIN_TABLE_LSN IS NOT NULL
BEGIN
INSERT INTO MY_AUDIT_TABLE (...columns...)
SELECT ... columns...
FROM cdc.fn_cdc_get_all_changes_dbo_MY_SOURCE_TABLE(@MIN_TABLE_LSN, @END_LSN, 'all update old') C
JOIN cdc.lsn_time_mapping T WITH (NOLOCK) ON T.start_lsn = C.__$start_lsn
ORDER BY __$start_lsn ASC, __$seqval ASC
END
现在,一些人甚至建议的唯一剩余替代方案是,此代码有时可能会从 AUDIT 表中选择最新的更改,然后将其增加到尚不存在的 LSN。但是我已经手动测试了很多次,它没有给出任何错误。此外,使用从另一个 CDC 表派生的 @END_LSN 值(该特定的 MY_AUDIT_TABLE 到目前为止还没有记录)也可以完美地工作。
我可以手动产生此错误的唯一方法是为函数提供比 lsn_time_mapping 表中存在的值更新的 @END_LSN 值。但这种情况只有在 SQL Server 可以实际创建带有 start_lsn 且在 lsn_time_mapping 中尚不存在的 CDC 表记录时才有可能,而且我认为这几乎是不可能的。或者是吗?这意味着您无法在该行刚刚可用时可靠地将 lsn 映射到日期时间。
像往常一样再次感谢您的帮助和解释。 :)
【问题讨论】:
-
正如您所说,我只在 LSN 参数表示无意义区间(即 min >= max)时看到此错误。我的建议是用
if @min_table_lsn < @end_lsn替换您的支票,因为这需要正确才能使获取更改功能正常工作。 -
是的,但我不明白为什么我无法重现该问题。我怀疑该函数使用一些 math.Random() 函数在我测试它时使用更大的 min > max 值可以很好地工作,但是当作业和过程执行相同的操作时有时会返回错误?但是,是的,我想我会尝试一下,看看接下来几天我是否会遇到这些错误。谢谢! :)
-
发生了奇怪的事情。我唯一的建议是记录过程中的值。我不能告诉你你会发现什么,但它几乎可以保证很有趣。
标签: sql-server sql-server-2012 cdc