php – 在mysql表中找到无法导出的“有问题”行

我想要backup my database with PHP.

我测试了链接的脚本,但它永远不会结束,我试图在查询之前添加修复$表,但它没有帮助.

所以我想出如果我只是跳过两个表(你可以在代码中看到)然后它工作正常:

<?

error_reporting(E_ALL);
ini_set('error_reporting',1);
require('../basedatos.php');

echo 'included<br>';
/* backup the db OR just a table */
function backup_tables($host,$user,$pass,$name,$tables = '*')
{


    echo '1<br>';
    //get all of the tables
    if($tables == '*')
    {
        $tables = array();
        $result = mysql_query('SHOW TABLES') or die(msyql_error());
        while($row = mysql_fetch_row($result))
        {
            $tables[] = $row[0];
        }
    }
    else
    {
        $tables = is_array($tables) ? $tables : explode(',',$tables);
    }
    echo '2<br>';
    //cycle through
    foreach($tables as $table)
    {
        if($table == 'etiquetas' || $table == 'links') continue;
        $repair = mysql_query("REPAIR table $table") or die(mysql_error());
        echo '3- '.$table.'<br>';
        $result = mysql_query('SELECT * FROM '.$table) or die(msyql_error());
        $num_fields = mysql_num_fields($result);

        $return.= 'DROP TABLE '.$table.';';
        $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table))  or die(msyql_error());
        $return.= "\n\n".$row2[1].";\n\n";

        for ($i = 0; $i < $num_fields; $i++) 
        {
            while($row = mysql_fetch_row($result))
            {
                $return.= 'INSERT INTO '.$table.' VALUES(';
                for($j=0; $j<$num_fields; $j++) 
                {
                    $row[$j] = addslashes($row[$j]);
                    $row[$j] = ereg_replace("\n","\\n",$row[$j]);
                    if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
                    if ($j<($num_fields-1)) { $return.= ','; }
                }
                $return.= ");\n";
            }
        }
        $return.="\n\n\n";

    }
    echo '4<br>';
    //save file
    $handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
}
backup_tables('localhost','username','password','*');
?>

有没有办法找到给我一个问题的行,所以我可以编辑/删除它们?

-PS-

此外,如果我不跳过它们,我不会得到任何错误(脚本永远不会结束,这就是为什么我添加了一些丑陋的日志..,任何想法为什么?

-编辑-

此外,如果我尝试通过,例如,sqlBuddy导出数据库,我也会收到错误:

解决方法:

正如许多人所说,这个脚本(以及简单的“通过PHP转储MySQL”)远非最佳,但仍然比没有备份更好.

由于您只能使用PHP访问数据库,因此您应该使用它来查找出错的地方.

以下是对脚本的修改,它只会将一个表转储到文件中.它是一个调试脚本,而不是用于生产的导出工具(但是,用它做你想做的事),这就是它在保存表的每一行后输出调试的原因.

正如Amit Kriplani所建议的那样,每次迭代都会将数据附加到目标文件中,但我不认为PHP内存是你的问题,如果你的内存不足你应该得到一个PHP错误,或者至少应该抛出一个HTTP 500由服务器而不是永远运行脚本.

function progress_export( $file, $table, $idField, $offset = 0, $limit = 0 )
{

    debug("Starting export of table $table to file $file");

    // empty the output file
    file_put_contents( $file, '' );
    $return = '';


    debug("Dumping schema");

    $return.= 'DROP TABLE '.$table.';';
    $row2 = mysql_fetch_row(mysql_query("SHOW CREATE TABLE $table"));
    $return.= "\n\n".$row2[1].";\n\n";


    file_put_contents( $file, $return, FILE_APPEND );

    debug("Schema saved to $file");




    $return = '';

    debug( "Querying database for records" );

    $query = "SELECT * FROM $table ORDER BY $idField";

    // make offset/limit optional if we need them for further debug
    if ( $offset && $limit )
    {
        $query .= " LIMIT $offset, $limit";
    }

    $result = mysql_query($query);

    $i = 0;
    while( $data = mysql_fetch_assoc( $result ) )
    {
        // Let's be verbose but at least, we will see when something goes wrong
        debug( "Exporting row #".$data[$idField].", rows offset is $i...");

        $return = "INSERT INTO $table (`". implode('`, `', array_keys( $data ) )."`) VALUES (";
        $coma = '';

        foreach( $data as $column )
        {
            $return .= $coma. "'". mysql_real_escape_string( $column )."'";
            $coma = ', ';
        }

        $return .=");\n";

        file_put_contents( $file, $return, FILE_APPEND );

        debug( "Row #".$data[$idField]." saved");

        $i++;

        // Be sure to send data to browser
        @ob_flush();
    }

    debug( "Completed export of $table to file $file" );
}



function debug( $message )
{
    echo '['.date( "H:i:s" )."] $message <br/>";
}


// Update those settings :

$host = 'localhost';
$user = 'user';
$pass = 'pwd';
$base = 'database';

// Primary key to be sure how record are sorted
$idField = "id"; 

$table   = "etiquetas";

// add some writable directory
$file = "$table.sql";


$link = mysql_connect($host,$user,$pass);
mysql_select_db($base,$link); 




// Launching the script
progress_export( $file, $table, $idField );

编辑脚本末尾的设置,并针对两个表中的一个运行它.

您应该在脚本仍处理时看到输出,并获取有关正在处理的行的一些引用,如下所示:

[23:30:13] Starting export of table ezcontentobject to file ezcontentobject.sql

[23:30:13] Dumping schema

[23:30:13] Schema saved to ezcontentobject.sql

[23:30:13] Querying database for records

[23:30:13] Exporting row #4, rows offset is 0…

[23:30:13] Row #4 saved

[23:30:13] Exporting row #10, rows offset is 1…

[23:30:13] Row #10 saved

[23:30:13] Exporting row #11, rows offset is 2…

[23:30:13] Row #11 saved

[23:30:13] Exporting row #12, rows offset is 3…

[23:30:13] Row #12 saved

[23:30:13] Exporting row #13, rows offset is 4…

[23:30:13] Row #13 saved

etc.

如果脚本完成…

那么你将有一个表的备份(小心,我没有测试生成的SQL)!

我猜它不会完成:

如果脚本没有到达第一个“导出行…”调试语句

然后问题是在查询时.

然后,您应该尝试使用偏移量和限制参数来限制查询,继续进行二分法以找出它挂起的位置

生成限制为1000个第一结果的查询的示例.

// Launching the script
progress_export( $file, $table, $idField, 0, 1000 );

如果脚本在挂起之前显示正在导出的某些行

在确定显示的最后一行ID之前,您应该尝试:

>再次运行脚本,看它是否挂在同一行.这是为了看看我们是否面临“随机”问题(它从来都不是随机的).
>向函数调用添加偏移量(请参阅可选参数),并第三次运行脚本,以查看它是否仍挂在同一行上.

例如50作为偏移量,一些大数字作为限制:

// Launching the script
progress_export( $file, $table, $idField, 50, 600000 );

这是为了检查它自己的行是否导致问题,或者它是否是临界行数/数据量…

>如果每次都返回相同的最后一行,请检查并给我们反馈.
>如果添加偏移量以可预测的方式更改最后处理的行,我们可能会在某处遇到资源问题.

如果您无法在分配的资源上播放,那么解决方案将是将导出拆分为块.
您可以使用接近此脚本的脚本完成此操作,输出一些HTML / javascript,重定向到它自己,使用offset和limit作为参数,而导出未完成(如果我们最终需要,我将编辑答案) )

>如果行几乎每次都改变,那就更复杂了……

一些线索:

我对VPS没有任何经验,但是你对CPU使用有什么限制吗?

如果您一次使用过多的资源,那么您的流程是否会排队?

那些没有问题的转储表怎么样?是否存在与两者一样大的表格导致问题?

上一篇:Fence Repair


下一篇:云计算学习路线教程大纲课件:XFS文件系统