webentwicklung-frage-antwort-db.com.de

Warum fängt dbDelta () MysqlErrors nicht ab?

Soweit ich sehen kann, soll dbDelta() Datenbankfehler unterdrücken, die während des Betriebs auftreten. Im Allgemeinen scheint dies der Fall zu sein, aber New Relic meldet immer noch MysqlErrors von der Funktion. Die genaue Fehlermeldung hat das folgende Format:

MysqlError: Table 'xxx.wp_yyy_posts' doesn't exist

Aus dbDelta() in /wp-admin/includes/upgrade.php haben wir:

// Fetch the table column structure from the database
$suppress = $wpdb->suppress_errors();
$tablefields = $wpdb->get_results("DESCRIBE {$table};");
$wpdb->suppress_errors( $suppress );

Es scheint, dass suppress_errors() seinen Job macht und verhindert, dass Fehlermeldungen auf dem Bildschirm angezeigt werden. Es scheint jedoch auch, dass diese Fehler tatsächlich nicht behandelt werden, wie unsere New Relic-Installation zeigt.

Verständlicherweise möchten wir alle möglichen Fehlerquellen in unserer Produktions-App beseitigen, damit wir das New Relic-Tool zur Verfolgung der tatsächlichen Fehlerraten verwenden und diese mit den Berichterstellungstools von New Relic verknüpfen können.

Gibt es einen zwingenden Grund, warum dbDelta() diesen Fehler nicht behandelt? Der einzige Grund, den ich mir vorstellen kann, ist, dass dies eine bewusste Designentscheidung ist, um die Entwicklung und Fehlerbehebung zu erleichtern. Es könnte für einen Entwickler schwierig sein, Probleme aufzuspüren, wenn dbDelta() Fehler vollständig unterdrückt. Natürlich könnte ein neuer Parameter/eine neue Option eingeführt werden, um anzugeben, ob diese automatische Fehlerunterdrückung erfolgen soll oder nicht (was das Abfangen des MysqlError zu einem Kinderspiel machen würde).

Dies wird in unserem Fall zu einem Problem, bei dem jeder einzelne Aufruf von install_blog() diesen Fehler erzeugt. Da wir eine große Installation mit mehreren Standorten ausführen, wird jedes Mal, wenn wir ein neues Blog erstellen, ein Fehler generiert.

3
rinogo

Wie von @Charleston Software Associates erwähnt, sollte die DESCRIBE-Abfrage nicht ausgeführt werden, wenn die Tabelle nicht vorhanden ist. Die beste Lösung sei, wie er betonte, zu verhindern, dass der Fehler überhaupt erst auftritt.

Patchen Sie dazu wp-admin/includes/upgrade.php wie folgt:

Ändern Sie die folgende Zeile von dbDelta ():

  $tablefields = $wpdb->get_results("DESCRIBE {$table};”);

zu:

    //Begin core hack - See http://wordpress.stackexchange.com/q/141971/10388
    $check_table = $wpdb->get_results("SHOW TABLES LIKE '".str_replace("_", "\_", $table)."';");
    if(!empty($check_table))
        $tablefields = $wpdb->get_results("DESCRIBE {$table};");
    else
        $tablefields = null;
    //End core hack

Dies ist nicht die sauberste Lösung (zumal es sich um einen Core-Hack handelt), aber es funktioniert zumindest für mich! Vielleicht hilft es jemand anderem.

UPDATE: Siehe meinen Kommentar unten. (Dies löst das Problem nicht vollständig, obwohl es ein Schritt in die richtige Richtung ist.)

1
rinogo

DB-Fehler dieses Typs sollten nur auf der Benutzeroberfläche angezeigt werden, wenn DB_DEBUG aktiviert ist. Auf einem Produktionssystem, das deaktiviert werden soll. Sie sollten diese Einstellung in der Datei wp-config.php für Ihre WP -Installation finden.

Sie können versuchen, die Fehler manuell zum "Verbergen" zu zwingen, indem Sie das globale EZSQL_ERROR zurücksetzen. Dies ist mein persönlicher Hack und wahrscheinlich keine Empfehlung oder Best Practice für die Arbeit mit dbDelta:

/**
 * Update the data structures on new db versions.
 *
 * @global object $wpdb
 * @param type $sql
 * @param type $table_name
 * @return string
 */
function dbupdater($sql,$table_name) {
    global $wpdb;
    $retval = ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name ) ? 'new' : 'updated';

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    $were_showing_errors = $wpdb->show_errors;
    $wpdb->hide_errors();
    dbDelta($sql);
    global $EZSQL_ERROR;
    $EZSQL_ERROR=array();
    if ( $were_showing_errors ) {
        $wpdb->show_errors();
    }

    return $retval;
}
0
Lance Cleveland