Make WordPress Core


Ignore:
Timestamp:
02/02/2014 10:06:42 PM (13 years ago)
Author:
nacin
Message:

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

props pento.
see #5932.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/wp-db.php

    r27074 r27075  
    157157         */
    158158        var $queries;
     159
     160        /**
     161         * The number of times to retry reconnecting before dying.
     162         *
     163         * @since 3.9.0
     164         * @access protected
     165         * @see wpdb::check_connection()
     166         * @var int
     167         */
     168        protected $reconnect_retries = 5;
    159169
    160170        /**
     
    11931203
    11941204        /**
    1195          * Connect to and select database
     1205         * Connect to and select database.
    11961206         *
    11971207         * @since 3.0.0
    1198          */
    1199         function db_connect() {
     1208         *
     1209         * @param bool $allow_bail Optional. Allows the function to bail, default true. If this is set
     1210         *                         to false, you will need to handle the lack of database connection
     1211         *                         manually. Available since 3.9.0.
     1212         *
     1213         * @return bool True with a successful connection, false on failure.
     1214         */
     1215        function db_connect( $allow_bail = true ) {
    12001216
    12011217                $this->is_mysql = true;
     
    12181234                }
    12191235
    1220                 if ( !$this->dbh ) {
     1236                if ( ! $this->dbh && $allow_bail ) {
    12211237                        wp_load_translations_early();
    12221238
     
    12381254" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
    12391255
    1240                         return;
    1241                 }
    1242 
    1243                 $this->set_charset( $this->dbh );
    1244 
    1245                 $this->set_sql_mode();
    1246 
    1247                 $this->ready = true;
    1248 
    1249                 $this->select( $this->dbname, $this->dbh );
     1256                        return false;
     1257                } else if ( $this->dbh ) {
     1258                        $this->set_charset( $this->dbh );
     1259                        $this->set_sql_mode();
     1260                        $this->ready = true;
     1261                        $this->select( $this->dbname, $this->dbh );
     1262
     1263                        return true;
     1264                }
     1265
     1266                return false;
     1267        }
     1268
     1269        /**
     1270         * Check that the connection to the database is still up. If not, try to reconnect.
     1271         *
     1272         * If this function is unable to reconnect, it will forcibly die.
     1273         *
     1274         * @since 3.9.0
     1275         *
     1276         * @return bool True if the connection is up.
     1277         */
     1278        function check_connection() {
     1279                if ( @mysql_ping( $this->dbh ) ) {
     1280                        return true;
     1281                }
     1282
     1283                $error_reporting = false;
     1284
     1285                // Disable warnings, as we don't want to see a multitude of "unable to connect" messages
     1286                if ( WP_DEBUG ) {
     1287                        $error_reporting = error_reporting();
     1288                        error_reporting( $error_reporting & ~E_WARNING );
     1289                }
     1290
     1291                for ( $tries = 1; $tries <= $this->reconnect_retries; $tries++ ) {
     1292                        // On the last try, re-enable warnings. We want to see a single instance of the
     1293                        // "unable to connect" message on the bail() screen, if it appears.
     1294                        if ( $this->reconnect_retries === $tries && WP_DEBUG ) {
     1295                                error_reporting( $error_reporting );
     1296                        }
     1297
     1298                        if ( $this->db_connect( false ) ) {
     1299                                if ( $error_reporting ) {
     1300                                        error_reporting( $error_reporting );
     1301                                }
     1302
     1303                                return true;
     1304                        }
     1305
     1306                        sleep( 1 );
     1307                }
     1308
     1309                // We weren't able to reconnect, so we better bail.
     1310                $this->bail( sprintf( ( "
     1311<h1>Error reconnecting to the database</h1>
     1312<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>
     1313<ul>
     1314        <li>Are you sure that the database server is running?</li>
     1315        <li>Are you sure that the database server is not under particularly heavy load?</li>
     1316</ul>
     1317<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>
     1318" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
     1319
     1320                // Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
     1321                dead_db();
    12501322        }
    12511323
     
    12631335                if ( ! $this->ready )
    12641336                        return false;
     1337
    12651338                /**
    12661339                 * Filter the database query.
     
    12821355                $this->last_query = $query;
    12831356
    1284                 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES )
    1285                         $this->timer_start();
    1286 
    1287                 $this->result = @mysql_query( $query, $this->dbh );
    1288                 $this->num_queries++;
    1289 
    1290                 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES )
    1291                         $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
     1357                $this->_do_query( $query );
     1358
     1359                // MySQL server has gone away, try to reconnect
     1360                if ( empty( $this->dbh ) || 2006 == mysql_errno( $this->dbh ) ) {
     1361                        if ( $this->check_connection() ) {
     1362                                $this->_do_query( $query );
     1363                        }
     1364                }
    12921365
    12931366                // If there is an error then take note of it..
     
    13251398
    13261399                return $return_val;
     1400        }
     1401
     1402        /**
     1403         * Internal function to perform the mysql_query call
     1404         *
     1405         * @since 3.9.0
     1406         *
     1407         * @access private
     1408         * @see wpdb::query()
     1409         *
     1410         * @param string $query The query to run
     1411         */
     1412        private function _do_query( $query ) {
     1413                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
     1414                        $this->timer_start();
     1415                }
     1416
     1417                $this->result = @mysql_query( $query, $this->dbh );
     1418                $this->num_queries++;
     1419
     1420                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
     1421                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
     1422                }
    13271423        }
    13281424
Note: See TracChangeset for help on using the changeset viewer.