When the MySQL server has "gone away," attempt to reconnect and retry the query.

props pento.
see #5932.

Built from https://develop.svn.wordpress.org/trunk@27075


git-svn-id: http://core.svn.wordpress.org/trunk@26948 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Nacin 2014-02-02 22:07:12 +00:00
parent 17828876fa
commit 43c7993c1a
1 changed files with 111 additions and 15 deletions

View File

@ -157,6 +157,16 @@ class wpdb {
*/
var $queries;
/**
* The number of times to retry reconnecting before dying.
*
* @since 3.9.0
* @access protected
* @see wpdb::check_connection()
* @var int
*/
protected $reconnect_retries = 5;
/**
* WordPress table prefix
*
@ -1192,11 +1202,17 @@ class wpdb {
}
/**
* Connect to and select database
* Connect to and select database.
*
* @since 3.0.0
*
* @param bool $allow_bail Optional. Allows the function to bail, default true. If this is set
* to false, you will need to handle the lack of database connection
* manually. Available since 3.9.0.
*
* @return bool True with a successful connection, false on failure.
*/
function db_connect() {
function db_connect( $allow_bail = true ) {
$this->is_mysql = true;
@ -1217,7 +1233,7 @@ class wpdb {
$this->dbh = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
}
if ( !$this->dbh ) {
if ( ! $this->dbh && $allow_bail ) {
wp_load_translations_early();
// Load custom DB error template, if present.
@ -1237,16 +1253,72 @@ class wpdb {
<p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
return;
return false;
} else if ( $this->dbh ) {
$this->set_charset( $this->dbh );
$this->set_sql_mode();
$this->ready = true;
$this->select( $this->dbname, $this->dbh );
return true;
}
$this->set_charset( $this->dbh );
return false;
}
$this->set_sql_mode();
/**
* Check that the connection to the database is still up. If not, try to reconnect.
*
* If this function is unable to reconnect, it will forcibly die.
*
* @since 3.9.0
*
* @return bool True if the connection is up.
*/
function check_connection() {
if ( @mysql_ping( $this->dbh ) ) {
return true;
}
$this->ready = true;
$error_reporting = false;
$this->select( $this->dbname, $this->dbh );
// Disable warnings, as we don't want to see a multitude of "unable to connect" messages
if ( WP_DEBUG ) {
$error_reporting = error_reporting();
error_reporting( $error_reporting & ~E_WARNING );
}
for ( $tries = 1; $tries <= $this->reconnect_retries; $tries++ ) {
// On the last try, re-enable warnings. We want to see a single instance of the
// "unable to connect" message on the bail() screen, if it appears.
if ( $this->reconnect_retries === $tries && WP_DEBUG ) {
error_reporting( $error_reporting );
}
if ( $this->db_connect( false ) ) {
if ( $error_reporting ) {
error_reporting( $error_reporting );
}
return true;
}
sleep( 1 );
}
// We weren't able to reconnect, so we better bail.
$this->bail( sprintf( ( "
<h1>Error reconnecting to the database</h1>
<p>This means that we lost contact with the database server at <code>%s</code>. This could mean your host's database server is down.</p>
<ul>
<li>Are you sure that the database server is running?</li>
<li>Are you sure that the database server is not under particularly heavy load?</li>
</ul>
<p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
// Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
dead_db();
}
/**
@ -1262,6 +1334,7 @@ class wpdb {
function query( $query ) {
if ( ! $this->ready )
return false;
/**
* Filter the database query.
*
@ -1281,14 +1354,14 @@ class wpdb {
// Keep track of the last query for debug..
$this->last_query = $query;
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES )
$this->timer_start();
$this->_do_query( $query );
$this->result = @mysql_query( $query, $this->dbh );
$this->num_queries++;
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES )
$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
// MySQL server has gone away, try to reconnect
if ( empty( $this->dbh ) || 2006 == mysql_errno( $this->dbh ) ) {
if ( $this->check_connection() ) {
$this->_do_query( $query );
}
}
// If there is an error then take note of it..
if ( $this->last_error = mysql_error( $this->dbh ) ) {
@ -1326,6 +1399,29 @@ class wpdb {
return $return_val;
}
/**
* Internal function to perform the mysql_query call
*
* @since 3.9.0
*
* @access private
* @see wpdb::query()
*
* @param string $query The query to run
*/
private function _do_query( $query ) {
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
$this->timer_start();
}
$this->result = @mysql_query( $query, $this->dbh );
$this->num_queries++;
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
}
}
/**
* Insert a row into a table.
*