mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-17 06:53:15 +00:00
Fix #1705 : MySQL connection might be lost after long operations
This commit is contained in:
@@ -15,11 +15,12 @@
|
||||
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
|
||||
* @link www.phraseanet.com
|
||||
*/
|
||||
abstract class connection_abstract extends PDO
|
||||
abstract class connection_abstract
|
||||
{
|
||||
protected $name;
|
||||
protected $credentials = array();
|
||||
protected $multi_db = true;
|
||||
protected $connection;
|
||||
|
||||
public function get_credentials()
|
||||
{
|
||||
@@ -42,8 +43,12 @@ abstract class connection_abstract extends PDO
|
||||
|
||||
public function ping()
|
||||
{
|
||||
if (null === $this->connection) {
|
||||
$this->initConn();
|
||||
}
|
||||
|
||||
try {
|
||||
$this->query('SELECT 1');
|
||||
$this->connection->query('SELECT 1');
|
||||
} catch (PDOException $e) {
|
||||
return false;
|
||||
}
|
||||
@@ -51,41 +56,16 @@ abstract class connection_abstract extends PDO
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $statement
|
||||
* @param array $driver_options
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function prepare($statement, $driver_options = array())
|
||||
{
|
||||
return parent::prepare($statement, $driver_options);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
return parent::beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
return parent::commit();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function server_info()
|
||||
{
|
||||
return parent::getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
|
||||
if (null === $this->connection) {
|
||||
$this->initConn();
|
||||
}
|
||||
|
||||
return $this->connection->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
interface connection_interface
|
||||
{
|
||||
|
||||
public function ping();
|
||||
|
||||
public function get_name();
|
||||
@@ -28,11 +27,5 @@ interface connection_interface
|
||||
|
||||
public function close();
|
||||
|
||||
public function prepare($statement, $driver_options = array());
|
||||
|
||||
public function beginTransaction();
|
||||
|
||||
public function commit();
|
||||
|
||||
public function server_info();
|
||||
}
|
||||
|
@@ -36,42 +36,45 @@ class connection_pdo extends connection_abstract implements connection_interface
|
||||
{
|
||||
$this->debug = $debug;
|
||||
$this->name = $name;
|
||||
if ($dbname)
|
||||
$dsn = 'mysql:dbname=' . $dbname . ';host=' . $hostname . ';port=' . $port . ';';
|
||||
else
|
||||
$dsn = 'mysql:host=' . $hostname . ';port=' . $port . ';';
|
||||
|
||||
$this->credentials['hostname'] = $hostname;
|
||||
$this->credentials['port'] = $port;
|
||||
$this->credentials['user'] = $user;
|
||||
$this->credentials['password'] = $passwd;
|
||||
|
||||
if ($dbname)
|
||||
$this->credentials['dbname'] = $dbname;
|
||||
|
||||
parent::__construct($dsn, $user, $passwd, $options);
|
||||
|
||||
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->query("
|
||||
SET character_set_results = 'utf8', character_set_client = 'utf8',
|
||||
character_set_connection = 'utf8', character_set_database = 'utf8',
|
||||
character_set_server = 'utf8'");
|
||||
$this->initConn();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function initConn()
|
||||
{
|
||||
$this->connection = null;
|
||||
|
||||
if (isset($this->credentials['dbname']))
|
||||
$dsn = 'mysql:dbname=' . $this->credentials['dbname'] . ';host=' . $this->credentials['hostname'] . ';port=' . $this->credentials['port'] . ';';
|
||||
else
|
||||
$dsn = 'mysql:host=' . $this->credentials['hostname'] . ';port=' . $this->credentials['port'] . ';';
|
||||
|
||||
$this->connection = new \PDO($dsn, $this->credentials['user'], $this->credentials['password'], array());
|
||||
|
||||
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->connection->exec("
|
||||
SET character_set_results = 'utf8', character_set_client = 'utf8',
|
||||
character_set_connection = 'utf8', character_set_database = 'utf8',
|
||||
character_set_server = 'utf8'");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $statement
|
||||
* @param type $driver_options
|
||||
* @return PDOStatement
|
||||
* @return void
|
||||
*/
|
||||
public function prepare($statement, $driver_options = array())
|
||||
public function disconnect()
|
||||
{
|
||||
if ($this->debug) {
|
||||
return new connection_pdoStatementDebugger(parent::prepare($statement, $driver_options));
|
||||
} else {
|
||||
return parent::prepare($statement, $driver_options);
|
||||
}
|
||||
$this->connection = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,6 +86,48 @@ class connection_pdo extends connection_abstract implements connection_interface
|
||||
connection::close_PDO_connection($this->name);
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (null === $this->connection) {
|
||||
$this->initConn();
|
||||
}
|
||||
|
||||
if (!method_exists($this->connection, $method)) {
|
||||
throw new \BadMethodCallException(sprintf('Method %s does not exist', $method));
|
||||
}
|
||||
|
||||
$tries = 0;
|
||||
|
||||
do {
|
||||
$tries++;
|
||||
try {
|
||||
set_error_handler(function ($errno, $errstr) {
|
||||
if (false !== strpos($errstr, 'Error while sending QUERY packet')) {
|
||||
throw new \Exception('MySQL server has gone away');
|
||||
}
|
||||
throw new \Exception($errstr);
|
||||
});
|
||||
|
||||
if ('prepare' === $method && $this->debug) {
|
||||
$ret = new connection_pdoStatementDebugger(call_user_func_array(array($this->connection, $method), $args));
|
||||
} else {
|
||||
$ret = call_user_func_array(array($this->connection, $method), $args);
|
||||
}
|
||||
restore_error_handler();
|
||||
|
||||
return $ret;
|
||||
} catch (\Exception $e) {
|
||||
restore_error_handler();
|
||||
|
||||
$found = (false !== strpos($e->getMessage(), 'MySQL server has gone away')) || (false !== strpos($e->getMessage(), 'errno=32 Broken pipe'));
|
||||
if ($tries >= 2 || !$found) {
|
||||
throw $e;
|
||||
}
|
||||
$this->initConn();
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $message
|
||||
|
Reference in New Issue
Block a user