Время ожидания запроса, ошибка намного раньше, чем превышение максимального времени ожидания

Мое приложение для Android подключается к базе данных, много раз во многих действиях через PHP. в PHP, у меня есть этот код для подключения базы данных

   class db_connect
{
protected $db_conn;
protected $db_name = "database";
protected $db_user;
protected $password;
protected $db_host ="localhost";function __construct($username,$pass) {

$this->db_user = $username;
$this->password = $pass;

}

function connect(){
$this->db_conn = new PDO("mysql:host=$this->db_host;
dbname=$this->db_name",$this->db_user,$this->password);
$this->db_conn->exec("set names utf8");
return $this->db_conn;
}
function disconnect()
{
$this->db_conn = null;
}

function __destruct() {
}
}

Итак, когда мне нужно подключить базу данных из другого класса, я просто делаю:

$dbconnect = new db_connect($user,$pass);
$connection = $dbconnect->connect();

затем после выполнения я делаю отключение как
$ Dbconnect-> разъединение ();

Мой Php5.ini имеет это: (Я не хочу менять его).

; Default timeout for socket based streams (seconds)
default_socket_timeout = 60

Но проблема в том, что, когда я пытаюсь подключиться к базе данных, она отвечает сообщением «время ожидания запроса истекло», всего за 4/5 секунд. затем, если я попробую еще раз, обычно это связано.
Кто-нибудь может подсказать, пожалуйста, что я делаю не так? Почему он отправляет сообщение о превышении времени ожидания запроса через 5 секунд, даже если у меня установлено время ожидания 60 секунд.

0

Решение

Я не уверен сразу, в чем ваша проблема (возможно, повторное открытие незакрытого соединения), однако я бы предложил использовать шаблон синглтона для вашего класса соединения.

Это выглядит примерно так

final class PdoWrapper{

protected static $_instance;
protected $_conn;
protected $db_name = "database";
protected $db_user = "user";
protected $password = "pass";
protected $db_host ="localhost";

private funciton __construct(){
$this->_conn = new PDO("mysql:host=$this->db_host;dbname=$this->db_name",$this->db_user,$this->password);
$this->_conn->exec("set names utf8");
}

private function __clone(){}

public static getInstance(){
if( !self::$_instance ){
self::$_instance = new self();
}
return self::$_instance;
}

public function getConnection(){
return $this->_conn;
}
}

И вы бы использовали это так

 $conn = PdoWrapper::getInstance()->getConnection();

Дело в том, что это будет поддерживать ваше соединение, поэтому вы всегда используете один и тот же, просто позвонив getInstance метод. Стоит отметить, что класс является окончательным и constructor а также clone функции являются частными для предотвращения дублирования этого класса и соединения с базой данных.

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

В повторе чтобы класс соединения принимал ввод для параметров соединения.

Хотя это на первый взгляд кажется весьма разумным и легко осуществимым, это несколько наивно. Чтобы объяснить это, возникает сложность, потому что, когда вы разрешаете ввод в класс, вы нарушаете природу шаблона «Singleton», который является единичным экземпляром с единой точкой доступа, в основном неизменным экземпляром класса (не может быть изменен после инициализации). Предотвращение мутации — вот почему класс помечается как окончательный (не может быть расширен) и имеет как частный __construct а также __clone метод.

Лучший способ объяснить это — сказать, что вы даете предпочтение при создании синглтона, передавая данные соединения. Таким образом, вам всегда придется создавать его с одинаковыми деталями соединения или сначала установить первоначальное соединение, прежде чем вы сможете его использовать. Чтобы еще больше усложнить это, вы открываете его для передачи различных сведений о соединении, и при этом не будет четкого способа узнать, какой набор учетных данных использовался в любой момент времени или какое соединение оно содержит. У вас также возникнет проблема с принятием решения о том, был ли инициирован класс (соединение) с этими данными или необходимо ли его повторно подключить, используя новые сведения о соединении.

К счастью, мы можем решить все эти проблемы, создав то, что я называю Multi-Singleton, что само по себе немного оксюморон. В любом случае, для этого вам понадобятся 2 файла, один для информации о соединении (файл конфигурации), поскольку вы не хотите, чтобы сведения о соединении с вашей базой данных были разбросаны по всему приложению. Подумайте о том дне, когда вы захотите обновить пароль своей базы данных, и вам придется искать во всем своем коде его копии.

Итак, мы начнем с этого файла (dbconf.php)

<?php
$conf = array();

$conf['database1'] = array(
'host' => 'localhost',
'user' => 'user1',
'pass' => 'pass1'
);

$conf['database2'] = array(
'host' => 'localhost',
'user' => 'user2',
'pass' => 'pass2'
);

В этом файле мы имеем многомерный массив с ключом верхнего уровня, соответствующим имени базы данных, а другие данные — это детали подключения к этой базе данных.

Затем мы вносим несколько небольших изменений в вышеприведенный класс. (это не было проверено, но должно показать общую идею)

<?php
final class PdoWrapper{

protected static $_instances = array();
protected static $_dbconf;
protected $_conn;

private funciton __construct( $database ){
if( !self::$_dbconf ){
require 'dbconf.php';
self::$_dbconf = $conf;
}

if( !isset( self::$_dbconf[$database] ) ){
die( 'Unknown database in '.__FILE__.' on '.__LINE__ );
}

$this->_conn = new PDO(
"mysql:host=" . self::_dbconf[$database]['host'] . ";dbname=$database",
self::_dbconf[$database]['user'],
self::_dbconf[$database]['pass']
);
$this->_conn->exec("set names utf8");
}

private function __clone(){}

public static getInstance( $database ){
if( !self::$_instance[$database] ){
self::$_instance[$database] = new self($database);
}
return self::$_instance[$database];
}

public function getConnection(){
return $this->_conn;
}
}

Здесь изменились импорт файла конфигурации и способ сообщить классу, какой экземпляр базы данных использовать. Теперь с этими изменениями вы называете класс следующим образом.

 $Conn1 = PdoWrapper::getInstance( 'database1' )->getConnection();
$Conn2 = PdoWrapper::getInstance( 'database2' )->getConnection();

Итак, как вы можете видеть, у вас может быть несколько синглетов, каждый из которых содержит ровно одно соединение с одной базой данных. При использовании этого метода предпочтение не устанавливается первому обращению к классу. Нет первоначального подключения, которое должно быть сделано. Кроме того, вам не нужно дублировать данные подключения к базе данных повсюду.

Последнее изменение, которое я хотел бы сделать, — добавить функцию ярлыка, подобную этой

public static function getInstanceConnection( $database ){
$I = self::getInstance( $database );
return $I->getConnection();
}

Хотя в этом нет необходимости, он позволяет сделать один вызов и немного лучше читать за пределами класса. Таким образом, чтобы дублировать код инициализации выше, вы должны сделать это после добавления этого метода в.

 $Conn1 = PdoWrapper::getInstanceConnection( 'database1' );
$Conn2 = PdoWrapper::getInstanceConnection( 'database2' );

Причина не просто в возврате соединения из getInstance Метод (помимо ясности именования) заключается в том, что вы можете добавить некоторые другие функции к последнему классу, и в этом случае вам потребуется доступ к самому экземпляру Singleton. Простой пример этого — добавить метод, чтобы увидеть, существует ли такая таблица.

public function tableExists( $table ){
$stmt = $this->_conn->prepare('SHOW TABLES LIKE :table');
$stmt->execute( array( ':table' => $table ) );
return $stmt->rowCount() ? true : false;
}

Тогда вам нужно получить экземпляр для его вызова.

$I = PdoWrapper::getInstance( 'database1' );
$I->tableExists( 'table' );
//or with method chaining you can do this.
PdoWrapper::getInstance( 'database1' )->tableExists( 'table' );

Вы никогда не знаете, какие функции вы можете добавить последним, поэтому всегда держите эти параметры открытыми.

По сути, это шаблон Singleton, объединенный с шаблоном Factory. Более подробную информацию о шаблонах программирования смотрите в этой вики-статье.

http://en.wikipedia.org/wiki/Software_design_pattern

1

Другие решения

Других решений пока нет …