假设我们有一个带有自增主键的表。我想加载所有大于我看到的最后一个 ID 的 ID。
SELECT id
FROM mytable
WHERE id > 10;
使用幼稚的方法,我冒着跳过 ID 的风险:
- 事务 1 声明 ID 11。
- 事务 2 声明 ID 12。
- 事务 2 提交。
- 我阅读了所有> 10的ID。我看到了 12,下次我会读取所有 >12 的 ID。我跳过了11。
- 事务 1 提交。出于所有意图和目的,ID 11 现在存在。
作为一种解决方案,我建议进行仔细检查以确保没有中间 ID 即将提交:
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
如果计数大于在第一个查询中看到的 ID 数,那么肯定有可能在该序列的间隙中提交额外的 ID。
问题是:反过来是否成立?如果计数等于(或小于)在第一个查询中看到的 ID 数,是否保证两者之间不会有任何值?还是我错过了一些可能的情况,即 ID 被认领,但READ UNCOMMITTED
查询还没有看到它们?
对于这个问题,请忽略:
- 手动插入 ID。
- 倒带自动增量计数器。