CDC fn_cdc_get_all_changes_dbo_ ошибка 313 "Недостаточное количество аргументов..."
Там нет недостатка в разделах, посвященных этой функции и ошибка "Недостаточное количество аргументов было предоставлено для процедуры или функции 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, который еще не существует. Но я проверял это вручную множество раз, и это не дает ошибок. Кроме того, использование значения @END_LSN, полученного из другой таблицы CDC, где этот конкретный MY_AUDIT_TABLE пока еще не имеет записей, работает также отлично.
Единственный способ, которым я могу создать эту ошибку вручную, это дать функции более новое значение @END_LSN, чем то, что существует в таблице lsn_time_mapping. Но такой сценарий возможен, только если SQL Server действительно может создавать записи таблицы CDC с start_lsn, которые еще не существуют в lsn_time_mapping, и я вряд ли думаю, что это возможно. Либо это? Это означает, что вы не можете надежно отобразить lsn на дату и время, когда строка только что стала доступна.
Спасибо за помощь и объяснения снова, как обычно.:)
2 ответа
Это
SELECT @MIN_TABLE_LSN = sys.fn_cdc_increment_lsn(@MIN_TABLE_LSN)
просто добавляет 1 к @MIN_TABLE_LSN. Не обязательно, что существует новый @Min_Table_Lsn. Поэтому, если у вас нет никаких изменений, @END_LSN может быть ниже, чем @Min_Table_Lsn, и функция cdc.fn_cdc_get_all_changes_dbo_MY_SOURCE_TABLE() может завершиться ошибкой.
Обратите внимание, что "Задание сканера CDC" добавляет фиктивный LSN (с идентификатором транзакции 0x0) каждые 5 минут в таблицу cdc.lsn_time_mapping, поэтому у вас могут быть сценарии, когда нет изменений, и сценарий может быть успешным или нет, в зависимости от того, когда вы запустить его.
Как упомянуто выше, вы должны изменить условие, что Min LSN ниже или равен End LSN
Я смог это исправить используя "полное имя"
Например. table - dbo.lookup_test, вам нужно передать dbo_lookup_test в sys.fn_cdc_get_min_lsn.
DECLARE @from_lsn binary(10), @to_lsn binary(10);
SET @from_lsn = sys.fn_cdc_get_min_lsn('dbo_lookup_test');
SET @to_lsn = sys.fn_cdc_get_max_lsn();
SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_lookup_test
(@from_lsn, @to_lsn, N'all');
GO
Очевидно, что приведенный выше код уже принял мой ответ к сведению, но требование именования таблиц "{schema}_{tablename}" не было очевидным, и SQL Server не помогал, давая ложное сообщение об ошибке.
Также обратите внимание, что lsn должен быть объявлен как двоичный (10). Он не может быть просто объявлен как двоичный файл. Это выдаст ту же ошибку.
Просто - если BeginLsn/FromLsn, который вы пытаетесь передать функции get_all_changes, недоступен в таблице изменений, эта ошибка выдается. По умолчанию установите значение minLsn (get_min_lsn) и передайте его функции. При действующем периоде хранения после каждого x числа дней данные таблицы изменений очищаются, поэтому вам следует убедиться, что вы устанавливаете FromLsn в доступное значение в таблице CT.