MySQL sort 分页重复数据(转载)

前两天在写一个东西的时候,测试的同学说发现一个问题,排序分页,第二页和第一页有重复数据,当时我看了一下,确实有这个问题,然后就想到几年前我就曾经遇到过这个问题,淘宝数据库内核月报上也做了说明,所以这个时候就体现出了老程序员的价值:踩过的坑多,坑坑相连也就都成了平地,考虑到很多人不知道这个问题,所以把原文转载过来,以期能够让更多的人看到,原文如下: 背景 6.5 号,小编在 Aliyun 的论坛中发现一位开发者提的一个问题,说 RDS 发现了一个超级大 BUG,吓的小编一身冷汗 = =!! 赶紧来看看,背景是一个 RDS 用户创建了一张表,在一个都是 NULL 值的非索引字段上进行了排序并分页,用户发现第二页和第一页的数据有重复,然后以为是 NULL 值的问题,把这个字段都更新成相同的值,发现问题照旧。详细的信息可以登录阿里云的官方论坛查看。 小编进行了尝试,确实如此,并且 5.5 的版本和 5.6 的版本行为不一致,所以,必须要查明原因。 原因调查 在 MySQL 5.6 的版本上,优化器在遇到 order by limit 语句的时候,做了一个优化,即使用了 priority queue。参考伪代码: while (get_next_sortkey()) { if (using priority queue) push sort key into queue else { if (no free space in sort_keys buffers) { sort sort_keys buffer; dump sorted sequence to ‘tempfile’; dump BUFFPEK describing sequence location into ‘buffpek_pointers’; } put sort key into ‘sort_keys’; } } if (sort_keys has some elements && dumped at least once) sort-dump-dump as above; else don’t sort, leave sort_keys array to be sorted by caller 使用 priority queue 的目的,就是在不能使用索引有序性的时候,如果要排序,并且使用了limit n,那么只需要在排序的过程中,保留 n 条记录即可,这样虽然不能解决所有记录都需要排序的开销,但是只需要 sort buffer 少量的内存就可以完成排序。 之所以 5.6 出现了第二页数据重复的问题,是因为 priority queue 使用了堆排序的排序方法,而堆排序是一个不稳定的排序方法,也就是相同的值可能排序出来的结果和读出来的数据顺序不一致。 5.5 没有这个优化,所以也就不会出现这个问题。 ...

January 26, 2019 · 1 min · 197 words · Bridge Li

MyBatis下最好的分页实现:mybatis-paginator使用入门

前两天写一个项目,发现在MyBatis下一个最好的分页实现类库mybatis-paginator,今天就写一篇其入门教程供大家参考。 先引入maven依赖 <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>1.2.15</version> </dependency> 从这个依赖中,我们可以看到 1 他是mybatis的一个插件,2 其开源在GitHub上,感兴趣的可以去GitHub上搜源码看看,既然是mybatis的插件,下一步肯定就是和mybatis的集成了. 和mybatis集成 ①. 新建一个mybatis.xml的配置文件,其内容如下: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="cacheEnabled" value="true" /> <setting name="lazyLoadingEnabled" value="true" /> </settings> <plugins> <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor"> <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect" /> <property name="asyncTotalCount" value="true" /> </plugin> </plugins> </configuration> ②. 和spring集成,即在spring-mybatis.xml中引入该文件 &#8230;&#8230; <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:mybatis.xml" /> <property name="typeAliasesPackage" value="cn.bridgeli.demo.entity" /> <property name="mapperLocations" value="classpath:cn/bridgeli/demo/mapper/*.xml" /> </bean> &#8230;&#8230; 因为这个文件太长,就不贴全文了,仅把位置这一块贴出来,当我们把这些配置工作做好之后,下一步就是如何使用了。 ...

April 26, 2015 · 2 min · 219 words · Bridge Li