对视图进行分页查询期间,视图涉及到的表的数据变化导致查询不一致

【 TiDB 使用环境】生产环境 /测试/ Poc
【 TiDB 版本】V8.1.0
【复现路径】
【遇到的问题:问题现象及影响】 创建一个视图,分页查询,在分页查询期间,如果视图中某张表的数据变化了,会导致查询结果和第一次查询时不一致

请问有没有什么好的办法来解决次问题

这个和视图没关系,视图和你直接查原始表一样的

1 个赞

你需要了解下隔离级别这个概念,TiDB 支持 RR (快照隔离)隔离级别,在快照隔离级别下

begin;  -- 开启一个事务
select xxx;    -- 接下来的几个查询,都是查询同一快照,所以数据不会变化
select xxx;
commit;  -- 最后 commit
1 个赞

你分页查询时,原表发生变化查询视图时查出的数据必然会发生变化的。

tidb好像支持时间旅行语法,查询视图时要保证所用到的表是同一个时间节点

肯定会不一致啊。

  1. 业务场景就不可能一致。分页展示是多次前后端的接口调用。每次接口调用的时间点就不是一个时间点。后端服务不可能查到一样的结果(除非这段期间内数据没修改过)。
  2. 即使加了order by time desc/asc 。同一个时间点可能存在多条数据,例如:一页展示10条数据,同一个时间点正好有12条数据。那么如果只是依照时间进行排序一定会乱序,参考官方文档 分页查询 | TiDB 文档中心 (pingcap.com)

非要一致也行,在gc时间内,使用闪回查询,查询语句在表名后面加上as of timestamp +时间 时间不变结果不变,可以保证一段时间是固定的,参考的例子:
select * from ttt as of TIMESTAMP ‘2024-11-22 16:00:00’ order by 1 limit 10,10

看看这个

https://docs.pingcap.com/zh/tidb/stable/dev-guide-use-stale-read#stale-read

https://docs.pingcap.com/zh/tidb/stable/stale-read

你需要在分页开始前,记录一个时间戳,以后的读取都根据这个时间戳读取历史数据。
另外读历史数据需要在gc时间内。

https://docs.pingcap.com/zh/tidb/stable/garbage-collection-overview

gc机制你也需要了解一下。

每次分页查询都是从前端到后端重新请求的,不是在一个请求里面分页查询出所有,所以这样不行

应该说是尽量在短时间内,如果数据没变的情况下,分页查询出来的数据是一致的。视图如果是一个复杂的SQL,特别容易出现这种问题,感觉好像无解,只有在第一次查询的时候把符合条件的数据复制一份,查询复制的结果才行

是的,但甲方就想要这样,很无奈。

这个倒是不错的选择