疑难杂症之分页问题
最近处理了一个老系统的两个BUG,其中一个觉得有些意思,拿出来分享下.
话说,公司一客户最近报告了一个分页的诡异的问题.在分面列表中,本应每页四条记录的,从第二页开始,会出现大于四条的情况,并且后面的分页的记录有可能会包含前面的记录.
上网站确认,问题的确存在.而且诡异的地方有:
第一页总不会有问题
除了第一页,其它的,每次刷新的记录都可能不一样.比如第一次会是4条,再一次会是或5或6..
检查代码是没有什么问题的,检查分页存储过程过程当时也没有发现有问题.在我们测试环境也还原不了.
根据客户报告的情况,问题是出现在最近.据客户说,最上了一个新的专题后,问题开始出现.但最近的访问量也较以前有所增加.
确定不了原因,决定过客户环境测试下.
后台发现是SQL语句使用不严谨引起的.但这个会在高数据库访问量时才会出现(?).在分页的过程中,通过存储过程拼接出来的SQL类似于:
SELECT * FROM (
SELECT TOP 4 * 2 fieldA, fieldB, fieldC
FROM tableName
WHERE filedPk NOT IN (
SELECT TOP 4 * 1 fieldPk FROM tableName
)
)T
其中:
TOP 4 * 2 中的4是分页大小,2是取第2页的记录
这个SQL在公司的测试环境是没有问题的,在客户的测试环境上也没有问题,只是在客户正式环境上,问题就出现了.
其实这里是使用了两个子查询,达到分页的目的.使用了TOP子句,可并没有指定ORDER BY子句.经过查联机丛书,在"SELECT 子句"介绍中,对ORDERY BY有这样的描述:
TOP n [PERCENT]
指定只从查询结果集中输出前 n 行。n 是介于 0 和 4294967295 之间的整数。如果还指定了 PERCENT,则只从结果集中输出前百分之 n 行。当指定时带 PERCENT 时,n 必须是介于 0 和 100 之间的整数。
如果查询包含 ORDER BY 子句,将输出由 ORDER BY 子句排序的前 n 行(或前百分之 n 行)。如果查询没有 ORDER BY 子句,行的顺序将任意。
"行的顺序将任意",这个就很明确了。因为两个TOP产生的记录集记录顺序都可能不一样,两个记录集之间做NOT IN操作,自然得不到预定的结果.这样就可以解释之前的问题:
为什么第一页总没有问题?
因为通过上面的语句,第一页取分页记录的SQL类似于:
SELECT * FROM (
SELECT TOP 4 * 1 fieldA, fieldB, fieldC
FROM tableName
WHERE filedPk NOT IN (
SELECT TOP 4 * 0 fieldPk FROM tableName
)
)T
所以NOT IN针对的是一个空的记录集,所以第一页总是正确的。
除了第一页,其它的,每次刷新的记录都可能不一样.比如第一次会是4条,再一次会是或5或6条?
因为没在使用ORDERY BY的情况下使用TOP,行的顺序将任意,所以就会有这样混乱的情况.
为什么在测试环境没有问题?
这个就比较困难了.下面是个人猜测的,主观原因比较强,仅供参考:
存储过程内部是通过拼接SQL的方式产生分页命令的;这些拼接出来的SQL需要通过数据库的优化过程,确定DBMS认为最佳的执行步骤;由于数据库访问量非常大,导致优化过程再为复杂,出现命令相同,但是最终执行步骤却不同的结果.最终导致了上面的结果.
PS:在测试环境没有发现问题的原因,其实就是学艺不精,使用SQL有5,6年了,这一点都没有看出来,继续学习吧...
- 1. 疑难杂症之分页问题2010-04-05
- 2. 身份证验证函数2010-04-04
- 3. 数据库主体在该数据库中拥有 架构,无法删除解决方法2010-02-03
- 4. 获得数据库的排它访问权2010-01-27
- 5. sp_MSForEachTable和sp_MSForEachDB的使用方法2009-08-03
- 6. 取数据库所有表的记录数2009-06-19
- 7. SQL语句优化建议2009-05-13
- 8. 得到字段相关的约束信息2008-11-24





