zoukankan      html  css  js  c++  java
  • 由 OR 引起的死循环


      在客商迁移测试时,程序一旦开始执行就不能自动停止。只能通过手动中断应用服务器的进程来停止。检查迁移的一个表,这个表迁移前没有数据,迁移最多会插入3w条左右数据,但是迁移过程执行2个多小时候再看,已经有32G了。
      首先,这个表没有blob等大对象字段,按正常情况肯定不会占用32G空间。因为整个迁移过程是一个事务,迁移不结束无法查看这个表的真实行数。这个时候怀疑程序有死循环。
    开发在联测代码时,发现下面这个SQL,第一次查询后,后面不管第几次查都跟第一次结果一样,这也就是导致死循环的原因。
    下面看下这个SQL:
    select pk_cubasdoc
    from (select row_number() over(order by PK_CUBASDOC asc) rn, pk_cubasdoc
    from src_cubasdoc
    where 1 = 1
    and (iscustomer = 'Y' and issupplier = 'Y')
    or (iscustomer = '~' and issupplier = '~')
    and pk_cubasdoc > '1006A3100000000YB5CP') tablewithrn
    where tablewithrn.rn < 20001;
    src_cubasdoc这个表有26917行记录,并且取出的数据插入到表itf_customer。
      虽然这条SQL的本意是,想在取出前2w条记录的基础上,循环取出后6917行数据。而pk_cubasdoc='1006A3100000000YB5CP'正是第2w条记录。但是结果呢,却总是取出来前2w行记录,无穷无尽成了死循环。
      为什么会成为死循环?对,是and和or优先级问题。既然要取后2w行记录,那么肯定是先对表src_cubasdoc条件过滤后再取pk_cubasdoc>'1006A3100000000YB5CP'的记录。
    现在的SQL却是按and (iscustomer = 'Y' and issupplier = 'Y') or ((iscustomer = '~' and issupplier = '~') and pk_cubasdoc > '1006A3100000000YB5CP'))的执行顺序。这样就跟是否pk_cubasdoc的条件关系不大了。也就是说按目前这种写法首先根本不是原意,还有一种副作用,就是怎么取都是前2w行。

      将SQL修改为:
     select pk_cubasdoc
    from (select row_number() over(order by PK_CUBASDOC asc) rn, pk_cubasdoc
    from src_cubasdoc
    where 1 = 1
    and ((iscustomer = 'Y' and issupplier = 'Y')
    or (iscustomer = '~' and issupplier = '~'))
    and pk_cubasdoc > '1006A3100000000YB5CP') tablewithrn
    where tablewithrn.rn < 20001;
    整个迁移过程不到10分钟结束。

    这个SQL就是or前后没有加括号导致的问题。
    写SQL时一定要注意,使用or时,一定要注意or的优先级没有and的高,如果先执行or必须将or前后子句加括号。
  • 相关阅读:
    git知识点总结
    自动化进阶
    unittest单元测试框架
    自动化测试模型
    webdriver
    python文件处理
    uva 11077 置换
    poj 1066 Treasure Hunt
    poj 2661 Factstone Benchmark
    hdu 4180
  • 原文地址:https://www.cnblogs.com/zhaoshuangshuang/p/3238007.html
Copyright © 2011-2022 走看看