无服务器配置权限下如何保证多SQL跨查询数据一致性且不阻塞事务
关联表数据迁移一致性无锁查询解决方案
核心通过数据库原生MVCC(多版本并发控制)的快照读能力实现,不需要修改服务器配置,也不会阻塞正常业务写入,完全满足你提出的所有要求。
实现前提
- 所用数据库支持MVCC(MySQL InnoDB、PostgreSQL、Oracle等主流关系型数据库默认支持)
- TRN_ID为顺序生成(自增ID、雪花ID等,数值随时间递增),或表内带有数据创建时间字段
推荐方案:全局一致性快照事务
该方案可以100%保证多个表查询的TRN_ID完全匹配,且完全屏蔽30秒查询窗口内的所有数据变更,全程无锁不阻塞写入:
- 第一步:先开启只读一致性事务,所有查询复用事务启动瞬间的全局数据快照
-- MySQL语法适配,其他数据库语法稍有差异但逻辑一致 SET TRANSACTION READ ONLY, ISOLATION LEVEL REPEATABLE READ; START TRANSACTION;
- 第二步:按顺序执行所有迁移查询,所有查询都使用同一个快照,完全不受后续写入操作影响
-- 查询TABLEA结果 SELECT * FROM TABLEA; -- 查询TABLE_SHORT结果,与后续TABLE_LONG的TRN_ID完全一致 SELECT * FROM TABLE_SHORT; -- 查询TABLE_LONG结果,复用同一快照,相同TRN_ID的行和TABLE_SHORT结果完全匹配 SELECT * FROM TABLE_LONG; -- 查询TABLEB关联结果,天然和第一步TABLEA的查询结果匹配,不会包含后续新增数据 SELECT * FROM TABLEB WHERE TRN_ID IN (SELECT TRN_ID FROM TABLEA);
- 第三步:所有查询完成后提交事务即可,不会修改任何数据
COMMIT;
注意:整个事务过程只有读操作,不会加任何表锁、行锁,正常业务的插入、更新操作完全不受影响,也不会出现查询报错的情况。
适配你给出的操作流程
如果你需要严格按照「查TABLEA→插入新数据→查TABLEB」的顺序执行,可以用截断标记方案:
- 第一步:提前获取当前最大的TRN_ID作为截断阈值
SELECT @cutoff_trn_id := MAX(TRN_ID) FROM TABLEA; - 第二步:执行
SELECT * FROM TABLEA WHERE TRN_ID <= @cutoff_trn_id获取TABLEA的结果 - 第三步:正常执行TABLEA、TABLEB的新数据插入操作,无任何阻塞
- 第四步:查询TABLEB时增加过滤条件,仅返回和第一步结果匹配的行
SELECT * FROM TABLEB WHERE TRN_ID <= @cutoff_trn_id;
该方案不需要开启长事务,同样可以保证两个表的TRN_ID完全一致,排除30秒窗口内的所有新增数据。
内容的提问来源于stack exchange,提问作者Branden
相关产品推荐
相关产品推荐

