Слишком много соединений при расширении Phalcon \ Db \ Adapter \ Pdo \ Mysql

0

Я попытался расширить Phalcon\Db\Adapter\Pdo\Mysql чтобы создать журнал каждый раз, когда функция запроса возвращает false.

Несмотря на то, что я не создаю никаких новых соединений, кроме одного в parent::__construct я получаю следующее исключение:

Fatal error: Uncaught PDOException: SQLSTATE[08004] [1040] Too many connections in ...Internal/Database/Mysql.php:14 Stack trace: #0 [internal function]: PDO->__construct('mysql:adapter=M...', '...', '...', Array) #1 [internal function]: Phalcon\Db\Adapter\Pdo->connect(Array) #2  .../Internal/Database/Mysql.php(14): Phalcon\Db\Adapter\Pdo->__construct(Array) #3 .../apps/bootstrap/app.php(378): Internal\Database\Mysql->__construct(Array) #4 [internal function]: Closure->{closure}() #5 [internal function]: Phalcon\Di\Service->resolve(NULL, Object(Phalcon\Di\FactoryDefault)) #6 .../apps/bootstrap/core_services.php(7): Phalcon\Di->get('logs') #7 [internal function]: Closure->{closure}() #8 [internal function]: Phalcon\Di\Service->resolve(NULL, Object(Phalcon\Di\FactoryDefault)) #9 .../apps/libs/Internal/Database/Mysql.php(15): Phalcon\Di->get('logger') #10 .../apps/bootstrap/app.php(37 in .../apps/libs/Internal/Database/Mysql.php on line 14

Код:

namespace Internal\Database;

use Phalcon\Db\Adapter\Pdo\Mysql as PhalconMysql;
use Phalcon\Di;

class Mysql extends PhalconMysql
{
    public $isLogger = false;

    public function __construct(array $descriptor)
    {
        parent::__construct($descriptor);
        $this->oLogger = Di::getDefault()->get('logger');
    }

    public function query($sqlStatement, $bindParams = null, $bindTypes = null)
    {
        $oResult = parent::query($sqlStatement, $bindParams, $bindTypes);
        if ($oResult === false && $this->isLogger === false) {
            $trace = debug_backtrace();
            $aCaller = array_shift($trace);
            $sFile = $aCaller['file'];
            $sLine = $aCaller['line'];
           $this->oLogger->error('MySQL query failed. File: ' . $sFile . ', Line: ' . $sLine, ['error' => $this->getErrorInfo()]);
    }
        return $oResult;
    }
}

Строкой, которая вызывает ошибку, является parent::__construct($descriptor); ,

Единственное другое изменение, которое я сделал, это заменить использование Phalcon\Db\Adapter\Pdo\Mysql с помощью Internal\Database\Mysql. Все соединения создаются так же, как и при использовании Phalcon\Db\Adapter\Pdo\Mysql.

Я посмотрел на родительские классы Phalcon\Db\Adapter\Pdo\Mysql. Единственное место, где я вижу созданное соединение, здесь

Я очень благодарен за вашу помощь в этом вопросе.

Теги:
exception
phalcon
pdo

4 ответа

1

Неправильно распространять классы в phalcon, которые фактически взаимодействуют с другими расширениями php. Выучил это с трудом.

Легкий способ, который я бы рекомендовал, - переопределить класс Mvc/Model, например. ModelCommon или BaseModel и реализуйте там Model::initialize и Model::afterFetch.

Но правильным способом было бы использовать механизм событий, разработанный в Phalcon. Трюк заключается в том, чтобы присоединяться к beforeQuery и/или afterQuery.

Ярлык для этого, сделанный в DI:

$di->set('db', function() use ($di) {
    $config = $di->getConfig();
    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql([
        // ...
    ]);

    $eventsManager->attach('db', function($event, $connection, $params) use ($config) {

        if ($event->getType() == 'beforeQuery') {
            // ...
        }

        if ($event->getType() == 'afterQuery') {
            // ...
        }
    });

    $connection->setEventsManager($eventsManager);
    return $connection;
});
  • 0
    Я бы предпочел расширить класс, потому что в реализации Phalcon отсутствуют важные функции. например. Метод вызова (хранимой процедуры) не существует. Я добавил это в расширение.
  • 0
    @KateGreenfield добавив функцию протоколирования непосредственно водителю SQL двигателя не exacly SOLID программирования. Я предоставил вам решение для регистрации событий в рамках шаблона проектирования Observer . То, что вы предпочитаете , не имеет для меня значения.
Показать ещё 2 комментария
0

Проблема решена, хотя я до сих пор не понимаю, почему это произошло в первую очередь.

Журнальный журнал регистрируется в базе данных, но поскольку он берется из Di, я предполагал, что он повторно использует существующее соединение. Удаление этой строки из конструктора и ее правильное после того, как логгер называется решаемой проблемой.

  • 0
    Это не решило проблему, просто ушло вовремя. То, что вы описали, - это ожидаемое поведение, когда либо служба logger не является «общей» при объявлении, либо вы не используете постоянные соединения для повторного использования между запросами. Если у вас больше трафика на вашем инструменте, вы столкнетесь с точно такой же проблемой.
  • 0
    @yergo служба регистрации доступна для декларации. Вот почему это удивляет меня.
0

Возможно, вы можете использовать службу db как общую, когда вы объявляете db в $ di

$di->setShared('db', function() {
    // return your db instance
});
  • 0
    это уже поделился
0

Похоже, модуль пытается подключиться к базе данных более одного раза. Возможно, убедитесь, что вы инициализируете службу базы данных только один раз в своем Module.php

  • 0
    Я не использую Module.php, все подключения БД добавляются в Di в начальной загрузке.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню