6

如果我比较两个 Magento 适配器类Varien_Db_Adapter_MysqliVarien_Db_Adapter_Pdo_Mysql我可以发现方法raw_query的查询异常处理的一些差异。

<?php

class Varien_Db_Adapter_Mysqli extends Zend_Db_Adapter_Mysqli
{

//....

/**
 * Run RAW Query
 *
 * @param string $sql
 * @return Zend_Db_Statement_Interface
 */
public function raw_query($sql)
{
    $timeoutMessage = 'SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded;      try restarting transaction';
    $tries = 0;
    do {
        $retry = false;
        try {
            $this->clear_result();
            $result = $this->getConnection()->query($sql);
            $this->clear_result();
        } catch (Exception $e) {
            if ($tries < 10 && $e->getMessage() == $timeoutMessage) {
                $retry = true;
                $tries++;
            } else {
                throw $e;
            }
        }
    } while ($retry);

    return $result;
}

//....

}

如果我将此与 Varien_Db_Adapter_Pdo_Mysql 中的 equal 方法进行比较,我会发现另一个错误处理。它不是检查超时,而是检查丢失的连接。

<?php

class Varien_Db_Adapter_Pdo_Mysql  extends Zend_Db_Adapter_Pdo_Mysql implements Varien_Db_Adapter_Interface
{

//....


/**
 * Run RAW Query
 *
 * @param string $sql
 * @return Zend_Db_Statement_Interface
 * @throws PDOException
 */
public function raw_query($sql)
{
    $lostConnectionMessage = 'SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query';
    $tries = 0;
    do {
        $retry = false;
        try {
            $result = $this->query($sql);
        } catch (Exception $e) {
            // Convert to PDOException to maintain backwards compatibility with usage of MySQL adapter
            if ($e instanceof Zend_Db_Statement_Exception) {
                $e = $e->getPrevious();
                if (!($e instanceof PDOException)) {
                    $e = new PDOException($e->getMessage(), $e->getCode());
                }
            }
            // Check to reconnect
            if ($tries < 10 && $e->getMessage() == $lostConnectionMessage) {
                $retry = true;
                $tries++;
            } else {
                throw $e;
            }
        }
    } while ($retry);

    return $result;
}

//....

}

那是对的吗?检查两个失败案例不是更好吗?

例子:

/**
 * Run RAW Query
 *
 * @param string $sql
 * @return Zend_Db_Statement_Interface
 * @throws PDOException
 */
public function raw_query($sql)
{
    $lostConnectionMessages = array(
        'SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query',
        'SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction',
    );
    $tries = 0;
    do {
        $retry = false;
        try {
            $result = $this->query($sql);
        } catch (Exception $e) {
            // Convert to PDOException to maintain backwards compatibility with usage of MySQL adapter
            if ($e instanceof Zend_Db_Statement_Exception) {
                $e = $e->getPrevious();
                if (!($e instanceof PDOException)) {
                    $e = new PDOException($e->getMessage(), $e->getCode());
                }
            }
            // Check to reconnect
            if ($tries < 10 && in_array($e->getMessage(), $lostConnectionMessages)) {
                $retry = true;
                $tries++;
            } else {
                throw $e;
            }
        }
    } while ($retry);

    return $result;
}
4

2 回答 2

2

我会说,是的,他们也应该检查一下。在Magento2 中,他们甚至删除了 lost-connection reconnect,但在 MysqlI 适配器中它仍然存在。

于 2012-07-06T16:56:36.537 回答
2

这取决于(总是一个很好的答案:)

我认为丢失的连接应该被视为系统设置中的错误。解决它的方法Varien_Db_Adapter_Pdo_Mysql隐藏了缓慢查询时间的根源。我宁愿看到真正的异常,然后让 Magento 尝试自动重新建立连接。

锁定等待超时也是如此。我想知道是否发生此类超时。用自动重试掩盖它们可能会使错误“消失”,但不能解决真正的问题。

这样的自动恢复代码至少应该可以通过系统配置中的某个选项进行配置,例如“启用数据库查询恢复模式”或类似的东西,并且默认为“禁用”。

于 2012-07-09T09:55:48.243 回答