MySQL 分页数据错乱重复

select xx from table_name wheere xxx order by 字段A limit offset;

表数据总共 48 条,分页数量正常,但出现了结果混杂的情况,第一页的数据出现在了第二页上;如果 order by 字段B 就不会出现这个现象,怎么会这样呢!

If multiple rows have identical values in the ORDER BY columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.

One factor that affects the execution plan is LIMIT, so an ORDER BY query with and without LIMIT may return rows in different orders.

问题重现

本次实验使用社区版 MySQL 5.6.26(因为小明出现问题的环境就是这个版本O(∩_∩)O~),下面先创建实验环境和初始化测试数据:

[email protected] [(none)]>select @@version;
+------------+
| @@version  |
+------------+
| 5.6.26-log |
+------------+
1 row in set (0.00 sec)

[email protected] [(none)]>show variables like "sql_mode";
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| sql_mode      | NO_ENGINE_SUBSTITUTION |
+---------------+------------------------+
1 row in set (0.00 sec)

[email protected] [(none)]>create database glon_ho;
Query OK, 1 row affected (0.04 sec)

[email protected] [(none)]>use glon_ho
Database changed

[email protected] [glon_ho]>create table glon(
    ->     id int not null auto_increment primary key,
    ->     name varchar(20) not null,
    ->     create_time datetime not null,
    ->     age tinyint unsigned default 18
    -> );
Query OK, 0 rows affected (0.01 sec)

[email protected] [glon_ho]>INSERT INTO `glon` VALUES (1, ‘Eason Chan‘, ‘2017-05-02 08:10:10‘, 19),(2, ‘Glon Ho‘, ‘2017-05-03 12:10:10‘, 18),(3, ‘赵敏‘, ‘2017-05-03 14:10:10‘, 17),(4, ‘Jacky Cheung‘, ‘2017-05-02 14:00:00‘, 22),(5, ‘周芷若‘, ‘2017-05-02 14:00:00‘, 16),(6, ‘Andy Lau‘, ‘2017-05-02 14:00:00‘, 50),(7, ‘至尊宝‘, ‘2017-05-02 14:00:00‘, 20),(8, ‘刘三姐‘, ‘2017-05-02 14:00:00‘, 19);
Query OK, 8 rows affected (0.01 sec)
Records: 8  Duplicates: 0  Warnings: 0

[email protected] [glon_ho]>select * from glon;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  2 | Glon Ho      | 2017-05-03 12:10:10 |   18 |
|  3 | 赵敏         | 2017-05-03 14:10:10 |   17 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  5 | 周芷若       | 2017-05-02 14:00:00 |   16 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
|  7 | 至尊宝       | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐       | 2017-05-02 14:00:00 |   19 |
+----+--------------+---------------------+------+
8 rows in set (0.00 sec)

这里创建了一个 glon 表,字段有自增 id, 姓名 name, 年龄 age, 及用户注册时间 create_time。

接着来复现问题

  • 根据用户注册时间 create_time 来排序:
[email protected] [glon_ho]>select * from glon ORDER BY create_time limit 0, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  8 | 刘三姐       | 2017-05-02 14:00:00 |   19 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
|  2 | Glon Ho   | 2017-05-03 12:10:10 |   18 |
|  3 | 赵敏      | 2017-05-03 14:10:10 |   17 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

可以看到两次查询结果中都出现了 id 为 8 的刘三姐,从上面初始化数据来看,总共有 8 条数据,现在不但分页出现重复数据,还丢了一条!

问题确实重现了,不过先不急,我们再来试多几组其他的排序方式。

  • create_time 和 age 组合排序
[email protected] [glon_ho]>select * from glon ORDER BY create_time,age limit 0, 4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  8 | 刘三姐     | 2017-05-02 14:00:00 |   19 |
|  7 | 至尊宝     | 2017-05-02 14:00:00 |   20 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,age limit 4, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
|  2 | Glon Ho      | 2017-05-03 12:10:10 |   18 |
|  3 | 赵敏         | 2017-05-03 14:10:10 |   17 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)
  • create_time 和 id 组合排序
[email protected] [glon_ho]>select * from glon ORDER BY create_time,id limit 0, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  5 | 周芷若       | 2017-05-02 14:00:00 |   16 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,id limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
|  2 | Glon Ho   | 2017-05-03 12:10:10 |   18 |
|  3 | 赵敏      | 2017-05-03 14:10:10 |   17 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)
  • 主键 id 排序
[email protected] [glon_ho]>select * from glon ORDER BY id limit 0, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  2 | Glon Ho      | 2017-05-03 12:10:10 |   18 |
|  3 | 赵敏         | 2017-05-03 14:10:10 |   17 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY id limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
|  5 | 周芷若    | 2017-05-02 14:00:00 |   16 |
|  6 | Andy Lau  | 2017-05-02 14:00:00 |   50 |
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

看到,后面的几组排序方式都没有再出现问题了,结合官档,我们知道 order by 排序的时候,如果排序字段中有多行相同的列值,则排序结果是不确定的。所以后面的几组组合形式的排序或者是主键 id 的排序,因为唯一性高,所以排序是确定的,不会出现结果混乱的问题。

那是不是可以就此结束了呢,no way, 我们再来看下面的实验,继续巩固一下:

  • 根据年龄 age 来排序:
[email protected] [glon_ho]>select * from glon ORDER BY age limit 0, 4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  3 | 赵敏       | 2017-05-03 14:10:10 |   17 |
|  2 | Glon Ho    | 2017-05-03 12:10:10 |   18 |
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY age limit 4, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  8 | 刘三姐       | 2017-05-02 14:00:00 |   19 |
|  7 | 至尊宝       | 2017-05-02 14:00:00 |   20 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

咦,这个排序也只是根据一个字段 age 来排序,怎么就没有出问题呢?不急,还有招:

[email protected] [glon_ho]>insert into glon values (9,‘乔峰‘,‘2017-05-03 13:10:10‘,22),(10,‘段誉‘,‘2017-05-03 15:10:10‘,19),(11,‘郭靖‘,‘2017-05-03 17:10:10‘,20),(12,‘黄蓉‘,‘2017-05-03 08:10:10‘,19);
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

[email protected] [glon_ho]>select * from glon;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  2 | Glon Ho      | 2017-05-03 12:10:10 |   18 |
|  3 | 赵敏         | 2017-05-03 14:10:10 |   17 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  5 | 周芷若       | 2017-05-02 14:00:00 |   16 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
|  7 | 至尊宝       | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐       | 2017-05-02 14:00:00 |   19 |
|  9 | 乔峰         | 2017-05-03 13:10:10 |   22 |
| 10 | 段誉         | 2017-05-03 15:10:10 |   19 |
| 11 | 郭靖         | 2017-05-03 17:10:10 |   20 |
| 12 | 黄蓉         | 2017-05-03 08:10:10 |   19 |
+----+--------------+---------------------+------+
12 rows in set (0.00 sec)

我又给 glon 表新增了几条数据,然后再来看看:

[email protected] [glon_ho]>select * from glon ORDER BY create_time limit 0, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  5 | 周芷若       | 2017-05-02 14:00:00 |   16 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
| 12 | 黄蓉      | 2017-05-03 08:10:10 |   19 |
|  2 | Glon Ho   | 2017-05-03 12:10:10 |   18 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time limit 8, 4;
+----+--------+---------------------+------+
| id | name   | create_time         | age  |
+----+--------+---------------------+------+
|  9 | 乔峰   | 2017-05-03 13:10:10 |   22 |
|  3 | 赵敏   | 2017-05-03 14:10:10 |   17 |
| 10 | 段誉   | 2017-05-03 15:10:10 |   19 |
| 11 | 郭靖   | 2017-05-03 17:10:10 |   20 |
+----+--------+---------------------+------+
4 rows in set (0.00 sec)

根据 create_time 排序,没有问题了,再来:

[email protected] [glon_ho]>select * from glon ORDER BY age limit 0, 4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  3 | 赵敏       | 2017-05-03 14:10:10 |   17 |
|  2 | Glon Ho    | 2017-05-03 12:10:10 |   18 |
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY age limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
| 12 | 黄蓉      | 2017-05-03 08:10:10 |   19 |
| 10 | 段誉      | 2017-05-03 15:10:10 |   19 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY age limit 8, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  7 | 至尊宝       | 2017-05-02 14:00:00 |   20 |
|  9 | 乔峰         | 2017-05-03 13:10:10 |   22 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

可以看到根据年龄 age 排序,问题出现了。

然后在看看组合的排序:

[email protected] [glon_ho]>select * from glon ORDER BY create_time,id limit 0, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  1 | Eason Chan   | 2017-05-02 08:10:10 |   19 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  5 | 周芷若       | 2017-05-02 14:00:00 |   16 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,id limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
| 12 | 黄蓉      | 2017-05-03 08:10:10 |   19 |
|  2 | Glon Ho   | 2017-05-03 12:10:10 |   18 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,id limit 8, 4;
+----+--------+---------------------+------+
| id | name   | create_time         | age  |
+----+--------+---------------------+------+
|  9 | 乔峰   | 2017-05-03 13:10:10 |   22 |
|  3 | 赵敏   | 2017-05-03 14:10:10 |   17 |
| 10 | 段誉   | 2017-05-03 15:10:10 |   19 |
| 11 | 郭靖   | 2017-05-03 17:10:10 |   20 |
+----+--------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,age limit 0, 4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  8 | 刘三姐     | 2017-05-02 14:00:00 |   19 |
|  7 | 至尊宝     | 2017-05-02 14:00:00 |   20 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,age limit 4, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
| 12 | 黄蓉         | 2017-05-03 08:10:10 |   19 |
|  2 | Glon Ho      | 2017-05-03 12:10:10 |   18 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY create_time,age limit 8, 4;
+----+--------+---------------------+------+
| id | name   | create_time         | age  |
+----+--------+---------------------+------+
|  9 | 乔峰   | 2017-05-03 13:10:10 |   22 |
|  3 | 赵敏   | 2017-05-03 14:10:10 |   17 |
| 10 | 段誉   | 2017-05-03 15:10:10 |   19 |
| 11 | 郭靖   | 2017-05-03 17:10:10 |   20 |
+----+--------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY age,id limit 0, 4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  3 | 赵敏       | 2017-05-03 14:10:10 |   17 |
|  2 | Glon Ho    | 2017-05-03 12:10:10 |   18 |
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY age,id limit 4, 4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
| 10 | 段誉      | 2017-05-03 15:10:10 |   19 |
| 12 | 黄蓉      | 2017-05-03 08:10:10 |   19 |
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon ORDER BY age,id limit 8, 4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
| 11 | 郭靖         | 2017-05-03 17:10:10 |   20 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  9 | 乔峰         | 2017-05-03 13:10:10 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

思考

既然排序不定,那么给排序字段加上索引会不会有用呢?

[email protected] [glon_ho]>alter table glon add index ix_age(age);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

[email protected] [glon_ho]>show create table glon\G
*************************** 1. row ***************************
       Table: glon
Create Table: CREATE TABLE `glon` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `create_time` datetime NOT NULL,
  `age` tinyint(3) unsigned DEFAULT ‘18‘,
  PRIMARY KEY (`id`),
  KEY `ix_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

[email protected] [glon_ho]>select * from glon order by age limit 0,4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  3 | 赵敏       | 2017-05-03 14:10:10 |   17 |
|  2 | Glon Ho    | 2017-05-03 12:10:10 |   18 |
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon order by age limit 4,4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
| 12 | 黄蓉      | 2017-05-03 08:10:10 |   19 |
| 10 | 段誉      | 2017-05-03 15:10:10 |   19 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
|  7 | 至尊宝    | 2017-05-02 14:00:00 |   20 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from glon order by age limit 8,4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  7 | 至尊宝       | 2017-05-02 14:00:00 |   20 |
|  9 | 乔峰         | 2017-05-03 13:10:10 |   22 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

也可以不在 order by 后面加多一列增加唯一性,可以改写成下面的形式:

[email protected] [glon_ho]>select * from (select distinct g.* from glon g order by age) t limit 0,4;
+----+------------+---------------------+------+
| id | name       | create_time         | age  |
+----+------------+---------------------+------+
|  5 | 周芷若     | 2017-05-02 14:00:00 |   16 |
|  3 | 赵敏       | 2017-05-03 14:10:10 |   17 |
|  2 | Glon Ho    | 2017-05-03 12:10:10 |   18 |
|  1 | Eason Chan | 2017-05-02 08:10:10 |   19 |
+----+------------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from (select distinct g.* from glon g order by age) t limit 4,4;
+----+-----------+---------------------+------+
| id | name      | create_time         | age  |
+----+-----------+---------------------+------+
| 10 | 段誉      | 2017-05-03 15:10:10 |   19 |
|  8 | 刘三姐    | 2017-05-02 14:00:00 |   19 |
| 12 | 黄蓉      | 2017-05-03 08:10:10 |   19 |
| 11 | 郭靖      | 2017-05-03 17:10:10 |   20 |
+----+-----------+---------------------+------+
4 rows in set (0.00 sec)

[email protected] [glon_ho]>select * from (select distinct g.* from glon g order by age) t limit 8,4;
+----+--------------+---------------------+------+
| id | name         | create_time         | age  |
+----+--------------+---------------------+------+
|  7 | 至尊宝       | 2017-05-02 14:00:00 |   20 |
|  9 | 乔峰         | 2017-05-03 13:10:10 |   22 |
|  4 | Jacky Cheung | 2017-05-02 14:00:00 |   22 |
|  6 | Andy Lau     | 2017-05-02 14:00:00 |   50 |
+----+--------------+---------------------+------+
4 rows in set (0.00 sec)

总之,如果发生了,最简单的方法就是在排序列(如 create time)上加索引,然后在 order by 上明示 primary key,这个问题就非常圆满的解决了。

总结

MySQL 使用 limit 进行分页时,可能会出现重复数据,通过加入 order by 子句可以解决,但是需要注意的是,如果排序字段有相同值的情况下,由于排序字段数据重复,可能会导致每次查询排序后结果顺序不同,分页还是会出现重复数据,这时可以加入第二个排序字段,提高排序的唯一性,最好保证排序的字段在表中的值是唯一的,这样就可以少写一个排序字段,增加查询效率,因为 order by 后面有多个排序字段时,无法用到索引。

推荐 2015年 06 月《数据库内核月报》的一篇旧文:MySQL · 答疑解惑 · MySQL Sort 分页

原文地址:https://www.cnblogs.com/zhuiluoyu/p/8127129.html

时间: 2024-11-08 12:01:57

MySQL 分页数据错乱重复的相关文章

解决mysql分页数据错乱问题

今天同事遇到个麻烦的问题,写了一个分页的功能,结果查出来的数据竟然有重复,有些数据同时在相邻的两页出现了, 但是查询总数据不分页的时候又只有一条,这里主要是排序的问题,在mysql中用 order by 排序的时候,如果排序字段中有相同的结果, 则排序结果是不确定的,每一个分页查询,这几个相同的数据就会乱序,导致查询的数据不准确,解决办法就是在需要用比较容易相等的 字段排序时,可以再增加一个排序字段,最后用id啥的,即:order by 字段A desc,Id desc; 记录一下,以后遇到了就

mysql 插入数据避免重复的手段

MySql避免重复插入记录 发布于: December 15, 2011, 6:02 pm 分类: MySQL 作者: Cyrec 阅读: [308] 今天用python抓取数据入库需要避免重复数据插入,在网上找了一些方法: 方案一:使用ignore关键字 如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用: insert ignore into table_name(email,phone,user_id) values('[email protec

SpringMVC+Mybatis实现的Mysql分页数据查询

周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下. 这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调函数和事件代理,有兴趣的朋友可以研究一下.后台的实现技术是将分页Pager作为一个实体对象放到domain层,当前页.单页数据量.当前页开始数.当前页结束数.总数据条数.总页数都作为成员属性放到实体类里面. 以前项目数据库用的是oracle,sql语句的写法会从当前页开始数到当前页结束数查询数据.刚刚在这纠结了很长时间,查询到的数据显示数量总是有偏差,后来

利用PHP实现MySQL表数据的简单分页

PHP实现MySQL表数据的简单分页 <?php  $conn=mysql_connect("127.0.0.1","root",'123456') or die("数据库连接失败"); mysql_select_db("ym"); mysql_query("set names utf8"); //获取数据的行数 $all=mysql_num_rows(mysql_query("select

MySQL 删除数据库中重复数据(以部分数据为准)

delete from zqzrdp where tel  in (select min(dpxx_id) from  zqzrdp  group by tel  having count(tel)>1); 执行,报错 异常意为:你不能指定目标表的更新在FROM子句.傻了,MySQL 这样写,不行,让人郁闷. 难倒只能分步操作,蛋疼 以下是网友写的,同样是坑爹的代码,我机器上运行不了. 1. 查询需要删除的记录,会保留一条记录.  代码如下 复制代码 select a.id,a.subject,

Oracle分页排序的实现与分页数据重复问题

对于关系数据库来说,直接写SQL拉数据在列表中显示是很常用的做法.但如此便带来一个问题:当数据量大到一定程度时,系统内存迟早会耗光.另外,网络传输也是问题.如果有1000万条数据,用户想看最后一条,这时即便有足够的内存,在网络上传输这么多数据也得一两小时吧,恐怕没几个用户有这么耐心等.因此分页是必须的. 现在网上的论坛.博客什么的,基本上都会有分页功能,有些是SQL分页的,有些可能是NOSQL用其它方法分页,都有很成熟的东西了.本文根据我自己的经验,以ORACLE为例,讲下简单的SQL分页和排序

MySQL大数据量分页查询方法及其优化

方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N 适应场景: 适用于数据量较少的情况(元组百/千级) 原因/缺点: 全表扫描,速度会很慢 且 有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3). Limit限制的是从结果集的M位置处取出N条输出,其余抛弃. 方法2: 建立主键或唯一索引, 利用索引(假设每页10条) 语句样式: MySQL中,可用如下方法: SELECT * FRO

mysql 大数据分页优化

一.mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 1.   直接用limit start, count分页语句, 也是我程序中用的方法: select * from product limit start, count当起始页较小时,查询没有性能问题,我们分别看下从10, 100, 1000, 10000开始分页的执行时间(每页取20条), 如下: select * from product limit 10, 20   0.016秒select * from prod

oracle 分页 数据重复 数据不正确

oracle 一般分页的写法为 select a.id,a.title,rownum as rn,a.create_time from                     (select a.* from temp a order by create_time desc) a  where rownum<=20 注意:我用的是 create_time 来进行排序 create_time 中有相等的 为了对比分页数据的差异我用left join 来看数据是否正常 这个是用的一个分页 我用了关联