【问题标题】:Why my Mysql look never stops为什么我的Mysql看起来永远不会停止
【发布时间】:2015-07-06 19:20:38
【问题描述】:

为什么我的 sql 循环永远不会结束? 我做了一个简单的光标while循环,但我得到一个无限循环,我找不到错误。 我没有性能问题,它是一个无限循环,我有 35K 条记录,但循环在此之后持续很长时间,直到我停止执行并且我无法理解它是怎么回事,循环应该是光标选择检索到的确切计数

DROP PROCEDURE IF EXISTS tlaTempAmoutUSDTrades;
CREATE PROCEDURE tlaTempAmoutUSDTrades()
BEGIN
  DECLARE bDone INT;
  DECLARE pTradeGUID binary(16);    -- or approriate type
  DECLARE pTradeAmountUSD double;    -- or approriate type
  DECLARE curs CURSOR FOR  SELECT t.guid FROM trades as t
    JOIN `orderslogadd` as `o` on`t`.`orderId` = `o`.`orderId`
    JOIN `currencypairs` as `ccp` on`o`.`ccpair` = `ccp`.`id`
    JOIN `currencies` as `ccy1` on`ccp`.`currency1` = `ccy1`.`id`
    JOIN `currencies` as `ccy2` on`ccp`.`currency2` = `ccy2`.`id`
    left  JOIN tlaAmountUSD tau on tau.guid = t.guid
    WHERE tau.amountUSD is  null ;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

    OPEN curs;

 setAmountUSD: LOOP
 FETCH curs INTO pTradeGUID;
        IF (bDone = 1) OR (pTradeGUID is null) THEN 
            LEAVE setAmountUSD;
        END IF;
        SET pTradeAmountUSD = (select  `crosUSDValV22`(`ccy1`.`id`,`ccy2`.`id`,`t`.`amount`,`t`.`amountCcy`,`t`.`dealtRate`,`t`.`guid`) as tradeAmountUSD
        FROM `trades` as t
        JOIN `orderslogadd` as `o` on`t`.`orderId` = `o`.`orderId`
        JOIN `currencypairs` as `ccp` on`o`.`ccpair` = `ccp`.`id`
        JOIN `currencies` as `ccy1` on`ccp`.`currency1` = `ccy1`.`id`
        JOIN `currencies` as `ccy2` on`ccp`.`currency2` = `ccy2`.`id`
        where t.guid=pTradeGUID);
        insert into tlaAmountUSD (guid,amountUSD) values (pTradeGUID,pTradeAmountUSD);

END LOOP setAmountUSD;

关闭 curs;

结束;

【问题讨论】:

标签: mysql select


【解决方案1】:

根据您在此处显示的内容,在从 curs 获取最后一行后,将调用 continue 处理程序,bDone 将设置为 1,然后条件测试将为真,并且将退出循环。这看起来不像是无限循环。

如果这是实际执行的代码,那么完成该过程只是需要时间。 (可能游标定义中的查询真的很慢,或者循环体中的查询真的很慢……被引用的表被锁定了,或者INSERT被阻塞了等等。 p>

为了调试这个,您可以考虑在游标查询上添加一个 LIMIT 1,看看您是否可以让它完成一行,看看需要多长时间。

您可以尝试注释掉正在执行该工作的过程的主体,然后执行一次提取,看看需要多长时间。

此外,对两个查询(在游标中和循环中)运行 EXPLAIN,验证是否使用了适当的索引,以及查询计划是否合理。还要测试这些查询,以验证它们是否返回了您期望的结果。

这将有助于缩小问题所在。


除非您指定不同的分隔符,否则所示的CREATE PROCEDURE 语句将引发错误;否则,遇到的第一个分号将(过早地)“结束”存储过程定义

 CREATE PROCEDURE tlaTempAmoutUSDTrades()
 BEGIN
   DECLARE bDone INT;
                    ^

要创建该过程,您需要执行以下操作:

 DELIMITER $$

 CREATE PROCEDURE tlaTempAmoutUSDTrades()
 BEGIN
   DECLARE bDone INT;
   -- ...
 END $$

 DELIMITER ;

【讨论】:

  • 我没有性能问题,它是一个无限循环,我有 35K 条记录,但循环在那之后持续很长时间,直到我停止执行并且我无法理解它是怎么回事,循环应该是光标选择检索的确切计数
  • 这不是您显示的代码中的无限循环。 SQL Fiddle demonstration here: http://sqlfiddle.com/#!9/32fbb/1。这将替换游标定义中的查询,更改pTradeGUID 的数据类型,并删除循环体。它运行得很好。正如我在回答中建议的那样......您可以采取一些简单的步骤来缩小实际问题所在。 (其他注意事项,我从不使用SET v = (SELECT,但如果那是无效的语法或引发错误,您应该会看到。crosUSDValV22 函数也是一个嫌疑犯。
  • 我强烈建议您缩小实际问题所在。我们无法从我们坐的地方调试它……我们只是在猜测。我们没有看到表定义,tlaAmountUSD 上是否定义了触发器,crosUSDValV22 函数的定义。我们所能做的就是推荐一些您可以采取的简单步骤来调试此问题。 (正如我在回答中指出的那样,甚至不清楚这是实际执行的代码......如果没有 DELIMITER 语句,CREATE PROCEDURE 语句将会失败。
猜你喜欢
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
  • 2022-11-26
  • 1970-01-01
  • 2013-06-10
  • 2013-06-17
相关资源
最近更新 更多