Welcome 微信登录

首页 / 数据库 / MySQL / Rownum分页故障解决一例

在目前很多系统中,界面数据分页(Page)已经成为一项通用功能。基本上,每种框架、结构和对应的数据库,都有一些成熟的现成解决方案。在Oracle中,rownum伪列是初学者非常容易用错的功能。本篇就介绍一个实际的分页和rownum结合使用时候的故障案例。(Oracle)Rownum释疑  http://www.linuxidc.com/Linux/2013-05/84637.htmOracle数据库学习之Rownum  http://www.linuxidc.com/Linux/2012-09/70061.htmOracle 中Rownum用法总结,Rownum 与 ROWID 区别 http://www.linuxidc.com/Linux/2012-07/66121.htmOracle利用Rownum和rowid分页 http://www.linuxidc.com/Linux/2012-04/58301.htmOracle数据库中Rownum分页 http://www.linuxidc.com/Linux/2012-02/53707.htmVMware+Linux+Oracle 10G RAC全程详细图解 http://www.linuxidc.com/Linux/2011-02/31976.htm在CentOS 6.4下安装Oracle 11gR2(x64) http://www.linuxidc.com/Linux/2014-02/97374.htmOracle 11gR2 在VMWare虚拟机中安装步骤 http://www.linuxidc.com/Linux/2013-09/89579p2.htmDebian 下 安装 Oracle 11g XE R2 http://www.linuxidc.com/Linux/2014-03/98881.htmOracle 11gR2 在VMWare虚拟机中安装步骤 http://www.linuxidc.com/Linux/2013-09/89579.htm1、问题简述 系统后台数据库采用Oracle 11gR2版本。  SQL> select * from v$version; BANNER--------------------------------------------------------------------------------Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit ProductionPL/SQL Release 11.2.0.3.0 - ProductionCORE11.2.0.3.0ProductionTNS for IBM/AIX RISC System/6000: Version 11.2.0.3.0 - ProductionNLSRTL Version 11.2.0.3.0 - Production  数据表inputfile_log记录数据文件日志信息。在界面上提供数据查询、操作和排序。界面提供所有字段的查询排序功能。数据表主键为inputfile_log_seq,一个字段为ISO_CODE。 在测试阶段,测试人员不时报出某些特定字段在排序过程中有一些问题,排序之后,跳转到下一页数据取值不变。但是,在架构层面,没有明显的故障和Bug存在,前端故障也大都是偶发性的。 一个偶然的机会,测试和开发人员定位到了问题的所在:对其他字段进行排序处理之后,分页功能一般不会有故障。只有在ISO_CODE进行排序,之后进行跳转分页的时候,才会有问题,而且问题也是偶发性,不具有必然性。 经过定位,发现页面前端输出的SQL语句有一些问题。页面前端采用Hibernate实体映射类。分页采用数据库“真分页”技术——数据库只把要显示的数据传递到前端。Hibernate负责SQL语句的生成执行。 定位的SQL语句为:  select *from (select a1.inputfile_log_seq, a1.ISO_CODE,rownum rwnfrom (select * from inputfile_log t order by t.ISO_CODE) a1where rownum <= 50)where rwn > 45;  Oracle中分页的语句方案很多,这种利用rownum取段的方法也是普遍接受的方法。问题在哪儿呢?下面我们执行语句看结果。   SQL> select *2from (select a1.inputfile_log_seq, a1.ISO_CODE,rownum rwn3from (select * from inputfile_log t order by t.ISO_CODE) a14where rownum <= 50)5where rwn > 45; INPUTFILE_LOG_SEQ ISO_CODERWN----------------- -------- ----------1901 AU461903 AU471906 AU481142 AU491157 AU50  SQL> select *2from (select a1.inputfile_log_seq, a1.ISO_CODE, rownum rwn3from (select * from inputfile_log t order by t.ISO_CODE) a14where rownum <= 55)5where rwn > 50; INPUTFILE_LOG_SEQ ISO_CODERWN----------------- -------- ----------1901 AU511903 AU521906 AU531142 AU541157 AU55  看出问题了,在SQL语句中,我们希望看到连续10条记录。但是虽然替换了数据段范围,但是结果集却是相同的。 反映到页面上,就是按照ISO_CODE进行排序之后,分页功能失效,点击跳到下一页,但是显示的数据却没有变化。 2、分析和实验 看似很诡异的问题,难道是Hibernate语句方案有问题?替换为其他的排序字段,问题似乎不存在。  SQL> select *2from (select a1.inputfile_log_seq, a1.ISO_CODE,rownum rwn3from (select * from inputfile_log t order by t.inputfile_log_seq) a14where rownum <= 55)5where rwn > 50; INPUTFILE_LOG_SEQ ISO_CODERWN----------------- -------- ----------997 AU51998 AU52999 AU531000 AU541001 AU55 SQL> SQL> select *2from (select a1.inputfile_log_seq, a1.ISO_CODE,rownum rwn3from (select * from inputfile_log t order by t.inputfile_log_seq) a14where rownum <= 50)5where rwn > 45; INPUTFILE_LOG_SEQ ISO_CODERWN----------------- -------- ----------992 AU46993 AU47994 AU48995 AU49996 AU50  排序结果正常。看来问题还是出在ISO_CODE上。 条条大路通罗马,换一种方法,试试结果如何呢?Oracle中还有很多其他的分页方案。  SQL> select *2from (select a1.inputfile_log_seq, a1.ISO_CODE,rownum rwn3from (select * from inputfile_log t order by t.ISO_CODE) a1)4where rwn > 455and rwn <= 50; INPUTFILE_LOG_SEQ ISO_CODERWN----------------- -------- ----------1316 AU461317 AU471318 AU481319 AU491323 AU50 SQL> SQL> select *2from (select a1.inputfile_log_seq, a1.ISO_CODE, rownum rwn3from (select * from inputfile_log t order by t.ISO_CODE) a1)4where rwn > 505and rwn <= 55; INPUTFILE_LOG_SEQ ISO_CODERWN----------------- -------- ----------1324 AU511865 AU521624 AU531163 AU541173 AU55  不采用问题SQL的两次截取方法,而是将所有的rownum都取出来实体化,再利用范围进行截取。这样做的结果也是正确的。 问题出在哪里呢?SQL本质上是一种描述性语句,只要我们正确描述,绝大多数情况是可以将正确的结果返回的。但是这个案例下,描述本身没有什么问题,而且错误出现是偶发性的,令人疑惑。 更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2014-05/101886p2.htm
  • 1
  • 2
  • 3
  • 下一页
Oracle Online Redefinition在线重定义MongoDB 日志太大的解决方法相关资讯      Rownum分页  Rownum 
  • 使用rowid和rownum获取记录时要注  (10/20/2014 18:51:40)
本文评论 查看全部评论 (0)
表情: 姓名: 字数

版权所有©石家庄振强科技有限公司2024 冀ICP备08103738号-5 网站地图