MySQL无自增字段的表如何定时查询新插入记录?
解决UUID主键表的增量查询问题
这确实是个挺头疼的场景——UUID主键没法用自增ID的套路,created字段又不能完全依赖,还只能读不能改表,数据量还大,NOT IN根本没法用。分享几个我实际项目里试过的可行方案:
方案1:本地维护已同步UUID+时间范围过滤
这是通用性最强的方案,不管UUID是啥版本都能用:
- 自己建个本地存储(比如小型数据库表、Redis集合都行),专门存已经拉取过的UUID
- 每次查询时,先设定一个缓冲时间范围(比如你每5分钟查一次,就查
created > 上次查询时间 - 1小时的记录),然后用LEFT JOIN过滤掉已经同步过的UUID:SELECT t.* FROM target_table t LEFT JOIN local_synced_uuid l ON t.uuid = l.uuid WHERE t.created > DATE_SUB(NOW(), INTERVAL 1 HOUR) -- 缓冲时间,覆盖可能的created滞后 AND l.uuid IS NULL - 把新拉取到的UUID插入本地存储,下次查询更新“上次查询时间”
优点&注意点:
- 完全不依赖UUID版本和插入顺序,只要有created字段就能用
- 缓冲时间要根据业务场景设够,比如如果偶尔有插入的记录created比实际时间晚1小时,那缓冲设1小时就够覆盖
- 本地存储可以定期清理旧UUID(比如只保留最近7天的),避免数据量过大影响查询效率
方案2:利用UUIDv1的时间特性(如果适用)
如果你的UUID是v1版本(大部分生成UUID的工具默认是v1,包含时间戳信息),那可以直接通过UUID本身判断插入顺序:
- UUIDv1的前12个字符(32位格式里的前两段)是时间戳的高位,插入顺序和这个时间戳是严格对应的
- 每次查询时记录最后拉取到的UUID,下次用这个UUID做条件:
SELECT * FROM target_table WHERE CONCAT(SUBSTRING(uuid, 1, 8), SUBSTRING(uuid, 9, 4)) > CONCAT(SUBSTRING(:last_uuid, 1, 8), SUBSTRING(:last_uuid, 9, 4)) OR (CONCAT(SUBSTRING(uuid, 1, 8), SUBSTRING(uuid, 9, 4)) = CONCAT(SUBSTRING(:last_uuid, 1, 8), SUBSTRING(:last_uuid, 9, 4)) AND uuid > :last_uuid) ORDER BY uuid ASC - 这个逻辑和自增ID的
WHERE id > :last_id本质一样,只是用UUID里的时间部分做排序依据
优点&注意点:
- 效率极高,不需要本地存储,直接用UUID做增量条件
- 但只适用于UUIDv1,如果是v4(完全随机)的话这个办法就失效了
避坑提醒
千万别用WHERE uuid NOT IN (:已拉取UUID列表),数据量大的时候这个查询会慢到离谱,而且列表长度还有限制,完全不适用。
内容的提问来源于stack exchange,提问作者eee
相关产品推荐
相关产品推荐

