为什么dbDelta()不能捕获MysqlErrors?

时间:2014-04-21 作者:rinogo

据我所见,dbDelta() 用于抑制在其操作过程中发生的数据库错误。一般来说,情况似乎是这样,但New Relic仍在报告函数中的MysqlErrors。准确的错误消息格式如下:

MysqlError: Table \'xxx.wp_yyy_posts\' doesn\'t exist
发件人dbDelta() 在里面/wp-admin/includes/upgrade.php, 我们有:

// Fetch the table column structure from the database
$suppress = $wpdb->suppress_errors();
$tablefields = $wpdb->get_results("DESCRIBE {$table};");
$wpdb->suppress_errors( $suppress );
看来suppress_errors() 正在完成它的工作,并防止错误消息回显到屏幕上。However, it also appears that these errors are not actually being handled, as shown by our New Relic installation.

可以理解的是,我们希望消除生产应用程序上所有可能的错误源,以便我们能够准确地使用New Relic工具跟踪实际错误率,并将其与New Relic的报告工具相关联。

Is there a compelling reason why dbDelta() doesn\'t handle this error? 我能想到的唯一原因是,这是一个经过深思熟虑的设计决策,旨在促进开发和bug修复。开发人员在以下情况下可能很难跟踪问题:dbDelta() 完全抑制任何错误。当然,可以引入一个新的参数/选项来指定是否应该发生这种自动错误抑制(这将使捕捉MysqlError变得轻而易举)。

在我们的案例中,这成为一个问题,在这种情况下install_blog() 生成此错误。由于我们正在运行大型多站点安装,因此每次创建新博客时,都会生成一个错误。

2 个回复
最合适的回答,由SO网友:rinogo 整理而成

正如@Charleston Software Associates提到的,如果表不存在,则不应执行descripe查询。正如他所指出的,最好的解决方案是首先防止错误的发生。

为此,请修补wp-admin/includes/upgrade.php 具体如下:

更改dbDelta()中的以下行:

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

    //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
这不是最干净的解决方案(尤其是因为它是一个核心黑客),但至少对我来说是可行的!也许这会帮助其他人。

更新:见下面我的评论。(这并不能完全解决问题,尽管这是朝着正确方向迈出的一步)

SO网友:Lance Cleveland

只有启用了DB\\U调试,该类型的DB错误才会出现在UI上。在应禁用的生产系统上。您应该在wp配置中找到该设置。用于WP安装的php文件。

您可以尝试通过重置EZSQL\\u全局错误来手动强制“隐藏”错误。这是我的个人技巧,可能不是使用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;
}

结束