Merge pull request #5192 from annando/quit-on-error
Reconnect or quit on lost database connection
This commit is contained in:
commit
d602da024f
2 changed files with 58 additions and 10 deletions
|
@ -119,6 +119,7 @@ if ($pid = pcntl_fork()) {
|
||||||
|
|
||||||
// We lose the database connection upon forking
|
// We lose the database connection upon forking
|
||||||
dba::connect($db_host, $db_user, $db_pass, $db_data);
|
dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||||
|
unset($db_host, $db_user, $db_pass, $db_data);
|
||||||
|
|
||||||
Config::set('system', 'worker_daemon_mode', true);
|
Config::set('system', 'worker_daemon_mode', true);
|
||||||
|
|
||||||
|
@ -143,10 +144,9 @@ while (true) {
|
||||||
Worker::spawnWorker($do_cron);
|
Worker::spawnWorker($do_cron);
|
||||||
|
|
||||||
if ($do_cron) {
|
if ($do_cron) {
|
||||||
// We force a disconnect and reconnect of the database connection.
|
// We force a reconnect of the database connection.
|
||||||
// This is done to ensure that the connection don't get lost over time.
|
// This is done to ensure that the connection don't get lost over time.
|
||||||
dba::disconnect();
|
dba::reconnect();
|
||||||
dba::connect($db_host, $db_user, $db_pass, $db_data);
|
|
||||||
|
|
||||||
$last_cron = time();
|
$last_cron = time();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,12 @@ class dba {
|
||||||
private static $errorno = 0;
|
private static $errorno = 0;
|
||||||
private static $affected_rows = 0;
|
private static $affected_rows = 0;
|
||||||
private static $in_transaction = false;
|
private static $in_transaction = false;
|
||||||
|
private static $in_retrial = false;
|
||||||
private static $relation = [];
|
private static $relation = [];
|
||||||
|
private static $db_serveraddr = '';
|
||||||
|
private static $db_user = '';
|
||||||
|
private static $db_pass = '';
|
||||||
|
private static $db_name = '';
|
||||||
|
|
||||||
public static function connect($serveraddr, $user, $pass, $db) {
|
public static function connect($serveraddr, $user, $pass, $db) {
|
||||||
if (!is_null(self::$db) && self::connected()) {
|
if (!is_null(self::$db) && self::connected()) {
|
||||||
|
@ -34,6 +39,12 @@ class dba {
|
||||||
|
|
||||||
$stamp1 = microtime(true);
|
$stamp1 = microtime(true);
|
||||||
|
|
||||||
|
// We are storing these values for being able to perform a reconnect
|
||||||
|
self::$db_serveraddr = $serveraddr;
|
||||||
|
self::$db_user = $user;
|
||||||
|
self::$db_pass = $pass;
|
||||||
|
self::$db_name = $db;
|
||||||
|
|
||||||
$serveraddr = trim($serveraddr);
|
$serveraddr = trim($serveraddr);
|
||||||
|
|
||||||
$serverdata = explode(':', $serveraddr);
|
$serverdata = explode(':', $serveraddr);
|
||||||
|
@ -112,6 +123,16 @@ class dba {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a reconnect of an existing database connection
|
||||||
|
*/
|
||||||
|
public static function reconnect() {
|
||||||
|
self::disconnect();
|
||||||
|
|
||||||
|
$ret = self::connect(self::$db_serveraddr, self::$db_user, self::$db_pass, self::$db_name);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the database object.
|
* Return the database object.
|
||||||
* @return PDO|mysqli
|
* @return PDO|mysqli
|
||||||
|
@ -451,23 +472,23 @@ class dba {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = '';
|
$param_types = '';
|
||||||
$values = [];
|
$values = [];
|
||||||
foreach ($args AS $param => $value) {
|
foreach ($args AS $param => $value) {
|
||||||
if (is_int($args[$param])) {
|
if (is_int($args[$param])) {
|
||||||
$params .= 'i';
|
$param_types .= 'i';
|
||||||
} elseif (is_float($args[$param])) {
|
} elseif (is_float($args[$param])) {
|
||||||
$params .= 'd';
|
$param_types .= 'd';
|
||||||
} elseif (is_string($args[$param])) {
|
} elseif (is_string($args[$param])) {
|
||||||
$params .= 's';
|
$param_types .= 's';
|
||||||
} else {
|
} else {
|
||||||
$params .= 'b';
|
$param_types .= 'b';
|
||||||
}
|
}
|
||||||
$values[] = &$args[$param];
|
$values[] = &$args[$param];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($values) > 0) {
|
if (count($values) > 0) {
|
||||||
array_unshift($values, $params);
|
array_unshift($values, $param_types);
|
||||||
call_user_func_array([$stmt, 'bind_param'], $values);
|
call_user_func_array([$stmt, 'bind_param'], $values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +511,27 @@ class dba {
|
||||||
$errorno = self::$errorno;
|
$errorno = self::$errorno;
|
||||||
|
|
||||||
logger('DB Error '.self::$errorno.': '.self::$error."\n".
|
logger('DB Error '.self::$errorno.': '.self::$error."\n".
|
||||||
System::callstack(8)."\n".self::replaceParameters($sql, $params));
|
System::callstack(8)."\n".self::replaceParameters($sql, $args));
|
||||||
|
|
||||||
|
// On a lost connection we try to reconnect - but only once.
|
||||||
|
if ($errorno == 2006) {
|
||||||
|
if (self::$in_retrial || !self::reconnect()) {
|
||||||
|
// It doesn't make sense to continue when the database connection was lost
|
||||||
|
if (self::$in_retrial) {
|
||||||
|
logger('Giving up retrial because of database error '.$errorno.': '.$error);
|
||||||
|
} else {
|
||||||
|
logger("Couldn't reconnect after database error ".$errorno.': '.$error);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
// We try it again
|
||||||
|
logger('Reconnected after database error '.$errorno.': '.$error);
|
||||||
|
self::$in_retrial = true;
|
||||||
|
$ret = self::p($sql, $args);
|
||||||
|
self::$in_retrial = false;
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self::$error = $error;
|
self::$error = $error;
|
||||||
self::$errorno = $errorno;
|
self::$errorno = $errorno;
|
||||||
|
@ -557,6 +598,13 @@ class dba {
|
||||||
logger('DB Error '.self::$errorno.': '.self::$error."\n".
|
logger('DB Error '.self::$errorno.': '.self::$error."\n".
|
||||||
System::callstack(8)."\n".self::replaceParameters($sql, $params));
|
System::callstack(8)."\n".self::replaceParameters($sql, $params));
|
||||||
|
|
||||||
|
// On a lost connection we simply quit.
|
||||||
|
// A reconnect like in self::p could be dangerous with modifications
|
||||||
|
if ($errorno == 2006) {
|
||||||
|
logger('Giving up because of database error '.$errorno.': '.$error);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
self::$error = $error;
|
self::$error = $error;
|
||||||
self::$errorno = $errorno;
|
self::$errorno = $errorno;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue