Moving Data Without Losing Any
The Check Takes Four Minutes a Day and Almost Nobody Runs It
Last timeThings That Arrive Late
Every failure in this course is detectable by comparing the two ends. Counts catch two of the four, values catch the rest, and a sample is enough.
Which check finds which failure
The first lesson named four ways data moves wrongly: loss, duplication,
corruption and reordering. Every lesson since has been about preventing one or
more of them. This one is about detecting them anyway, on the reasonable
assumption that something in the design is wrong and nobody knows which part.
The checks available are not interchangeable, and the mapping is worth having
precisely because the cheapest check is also the most popular and covers half the
cases.
| a count at each end | a sum or hash of values | a row by row comparison | a check on sequence or o | |
|---|---|---|---|---|
| loss | 1 | 1 | 1 | 0 |
| duplication | 1 | 1 | 1 | 0 |
| corruption | 0 | 1 | 1 | 0 |
| reordering | 0 | 0 | 1 | 1 |
Counts. Compare the number of records at each end for a bounded range, by
event time rather than arrival. Cheap, fast, and it catches both loss and
duplication. It is the right first check and it should be running everywhere.
A sum or a hash. Total a numeric column at each end, or hash the
concatenated values of the fields that matter and compare the hashes. This
catches corruption, including the cases counts cannot: a truncated string, a
rounded amount, a timezone applied twice, a field that silently became null. It
costs a full read at each end for the range being checked, which is why it gets
run on a sample or on a chunked schedule rather than continuously.
Row by row. Compare identified rows field by field, which tells you not only
that something is wrong but which rows and which fields. This is the diagnostic
tool rather than the monitor: too expensive to run across everything, exactly
what you want once a cheaper check has gone red.
Sequence or order. Compare positions rather than contents: are the sequence
numbers contiguous, did anything arrive out of order, is any position missing
from the middle. Almost nobody runs this, and it is the only thing that detects
reordering, which is why reordering is the failure that survives longest in
production systems.
COUNTS, by event time, over a closed window
select count(*) from source
where happened_at >= :from and happened_at < :to
-- and the same against the destination, then compare
VALUES, a sum for numbers and a hash for everything else
select sum(amount) from source where ...
select md5(string_agg(id || field_a || field_b, order by id))
ROW BY ROW, on a sample of identifiers
select id, field_a, field_b from source where id in :sample
-- same from the destination, compare field by field
SEQUENCE, for a stream carrying positions
select max(position) - min(position) + 1 - count(*) as missing
from destination where position between :from and :toWhy counts are not enough
Equal counts feel like proof and are not. Three cases make the point.
A row arrives with one field wrong. The counts match exactly. Nothing about the
number of rows is affected by a truncated name, an amount rounded to the wrong
precision, or a timestamp that passed through a timezone conversion twice.
A duplicate and a loss in the same window. One record was lost and another
duplicated, so the counts match and two separate things are wrong. This is less
of a coincidence than it sounds, because both failures tend to cluster around the
same events: a restart, a redeploy, a failover.
And a reordering. Every row present, every value correct, the counts identical,
and a sequence of state changes applied in the wrong order so the final state is
wrong. For anything that processes transitions rather than values, this is the
failure that produces the least explicable data, and no count or sum detects it.
The lesson stops here
4 more paragraphs to go
You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.
The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.
See the planThe contentsThis is the reading half
Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.
The contents