Suppose we have a table with an auto-increment primary key. I want to load all IDs greater than the last ID I have seen.
SELECT id
FROM mytable
WHERE id > 10;
With the naive approach, I risk skipping IDs:
- Transaction 1 claims ID 11.
- Transaction 2 claims ID 12.
- Transaction 2 commits.
- I read all IDs >10. I see 12, and next time I will read all IDs >12. I have skipped 11.
- Transaction 1 commits. For all intents and purposes, ID 11 now exists.
As a solution, I propose to do a double check to ensure that no intermediate IDs are about to be committed:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT COUNT(*)
FROM mytable
WHERE id > 10
AND id <= 12; -- Where 12 was the max seen in the first query
If the count is greater than the number of IDs seen in the first query, then it is definitely possible that additional IDs will be committed in the gaps in that sequence.
The question is: does the reverse hold true? If the count is equal to (or less than) the number of IDs seen in the first query, is it guaranteed that there will be no values in between? Or am I missing some possible scenario where the IDs are being claimed, yet the READ UNCOMMITTED
query does not see them yet?
For this question, please disregard:
- Manual ID insertions.
- Rewinding the auto-increment counter.