There's no shortage of topics covering this function and error "An insufficient number of arguments were supplied for the procedure or function cdc.fn_cdc_get_all_changes". I've checked most of them, but can't figure out what's wrong.
The problem here specifically is that I can't even reproduce this. It just appears randomly a few times per day or two, and goes away in mere seconds, so usually I can only see it in the job history as a failed run.
All sources I've browsed say it typically comes from using the function to fetch data from a time range where the capture instance doesn't have data. But as the code below will show you, the values are checked for just these type of exceptions before running the function.
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
Now the only remaining alternatives which some people have even suggested, is that this code may sometimes pick the latest change from the AUDIT table and then increment that to an LSN that doesn't yet exist. But I've tested this manually tons of times, and it gives no errors. Also, using an @END_LSN value derived from another CDC table, where this particular MY_AUDIT_TABLE doesn't have records that far yet, works perfectly as well.
The only way I can produce this error manually, is by giving the function a newer @END_LSN value than what exist in lsn_time_mapping table. But such a scenario is only possible if SQL Server can actually create CDC-table records with start_lsn's that don't yet exist in lsn_time_mapping, and I hardly think that's possible. Or is it? That would mean that you can't reliably map an lsn to a datetime at the time the row has just become available.
Thanks for help and explanations again, as usual. :)
if @min_table_lsn < @end_lsn
since that needs to be true for the get changes function to work properly. – Sherwin