mysql 分页 - 避免向客户端丢失或重复数据

Posted

技术标签:

【中文标题】mysql 分页 - 避免向客户端丢失或重复数据【英文标题】:mysql pagination - avoid missing or duplicate data to client 【发布时间】:2016-06-22 10:04:37 【问题描述】:

我在 mysql 中有一张这样的表

CREATE TABLE `usermst` (
  `userid` smallint(5) unsigned NOT NULL,
  `username` varchar(45) NOT NULL,
  `insdate` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

数据如下

insert into usermst(userid, username)
values (1, "user 1"),
       (2, "user 2"),
       (3, "user 3"),
       (4, "user 4"),
       (5, "user 5"),
       (6, "user 6"),
       (7, "user 7"),
       (8, "user 8"),
       (9, "user 9"),
       (10, "user 10");

如果我用 4 条记录(分页)查询第一页,它的工作正常。

select * from usermst order by insdate desc, userid desc limit 0,4;

输出:

userid  username insdate
10      user 10  2016-03-08 12:32:04.239335
9       user 9   2016-03-08 12:32:04.239335
8       user 8   2016-03-08 12:32:04.239335
7       user 7   2016-03-08 12:32:04.239335

使用以下查询请求第二页

select * from usermst order by insdate desc, userid desc limit 4,4;

输出:

userid  username insdate
6       user 6   2016-03-08 12:32:04.239335
5       user 5   2016-03-08 12:32:04.239335
4       user 4   2016-03-08 12:32:04.239335
3       user 3   2016-03-08 12:32:04.239335

但是,如果以某种方式删除了 page1 的记录,客户端的数据将丢失。或在 page1 中插入的记录(根据我的查询排序),将在客户端获取重复数据。 如何防止这个错误?

【问题讨论】:

我真的不明白这个问题,为什么会丢失数据以及为什么会有重复 问题不清楚 如果数据不再存在,它不应该对客户端可用。但是,如果您想避免这个“错误”,您可以将整个数据提取到 php 数组中并对这些数据进行分页,而不是进行新的查询。 嗨 @xpy 和 vigikaran,如果在第二次查询触发之前删除用户 ID 9 会发生什么。 关于插入,问题是,您是否要在结果集中包含这些新记录?关于删除,问题是,在某些页面上显示更少的记录是否重要?最后一个问题,如果单击 prev->next 或 next->prev,页面 #N 的结果集是否会发生变化? 【参考方案1】:

我将使用的方法是将您的分页基于排序列值 - 但仅在遍历页面时(下一个/上一个按钮)。当希望导航到特定页码时,仍然必须使用您现有的方法,但我认为您描述的问题确实是使用 Next / Prev 按钮导航时的问题。

对于每个“下一页”,获取“insdate”小于上一页获取的最后一个“insdate”的所有行。

第一页:

SELECT * FROM usermst ORDER BY insdate DESC, userid DESC LIMIT 0,4;
SELECT @prevInsDate := insdate, @prevUserId := userid FROM usermst 
    ORDER BY insdate DESC, userid DESC LIMIT 3,1;

对于下一页(第二页):

SELECT * FROM usermst 
WHERE insdate <= @prevInsDate AND userid < @prevUserId
ORDER BY insdate DESC, userid DESC LIMIT 0,4;

SELECT @prevInsDate := insdate, @prevUserId := userid FROM usermst 
    ORDER BY insdate DESC, userid DESC LIMIT 7,1;

@prevInsDate 和 @prevUserId 已被声明为变量。

【讨论】:

以上是关于mysql 分页 - 避免向客户端丢失或重复数据的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 分页 数据丢失问题解决

sqlserver分页去重失效

Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?

Mysql在可重复读事务隔离级别下怎么解决幻读的

MySQL使用union导致数据丢失的解决办法

TCP的重传规则是啥?