首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在mysql表中找到无法导出的“有问题的”行

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

Stack Overflow用户
提问于 2013-08-01 17:26:22
回答 5查看 563关注 0票数 3

我想要用PHP备份我的数据库

我测试了链接的脚本,但是它永远不会结束,我试图在查询之前添加repair $table,但是它没有帮助。

因此,我想如果我跳过两个表(您可以在代码中看到),那么它工作得很好:

代码语言:javascript
运行
复制
<?

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导出数据库,我也会得到错误:

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-08-09 00:54:56

正如许多人所指出的那样,这个脚本(以及简单的“通过PHP转储MySQL”的方式)远非最优,但仍然比根本没有备份更好。

因为您只能使用PHP来访问数据库,所以您应该使用它来找出出了什么问题。

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

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

代码语言:javascript
运行
复制
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启动表ezcontentobject的导出以文件ezcontentobject.sql 23:30:13倾销模式 23:30:13模式保存到ezcontentobject.sql 23:30:13查询记录数据库 23:30:13导出行#4,行偏移量为0. 23:30:13第4排得救 23:30:13出口行#10,行偏移为1. 23:30:13 #10行得救 23:30:13出口行#11,行偏移为2. 23:30:13 #11行得救 23:30:13出口行#12,行偏移为3. 23:30:13 #12行得救 23:30:13出口行#13,行偏移为4. 23:30:13行得救 等。

如果剧本完成了..。

好的,您将备份您的表(请注意,我没有测试生成的SQL)!

我想它不会完成的:

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

然后问题是在查询时。

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

生成仅限于1000个第一结果的查询的示例。

代码语言:javascript
运行
复制
// Launching the script
progress_export( $file, $table, $idField, 0, 1000 );

如果脚本显示挂起前导出的一些行

在对显示的最后一行id进行定罪之前,应尝试:

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

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

代码语言:javascript
运行
复制
// Launching the script
progress_export( $file, $table, $idField, 50, 600000 );

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

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

如果不能处理分配的资源,那么解决方案将是将导出分割成块。您可以使用一个接近此脚本的脚本来完成这一任务,输出一些HTML/javascript,将偏移量和限制作为参数重定向到它,而导出尚未完成(如果最终需要的话,我将编辑答案)。

  • 如果每一次发生变化,情况会变得更加复杂.

一些线索:

我没有使用VPS的经验,但是您对CPU的使用难道没有一些限制吗?

如果您一次使用过多的资源,您的进程是否在某种程度上被排队?

那么那些没有问题就被抛出的桌子呢?是否有像这两张桌子那么大的桌子造成了这个问题?

票数 2
EN

Stack Overflow用户

发布于 2013-08-01 17:38:24

我不知道为什么这个“街区”..。但是这个脚本只适用于非常基本的数据库。

例如,它如何处理外键约束?这只是一个建议,可能是故意放弃的,但为什么不使用mysql_dump呢?

从你的壳里:

代码语言:javascript
运行
复制
mysql_dump -h host -u user -p my_database > db-backup.sql

编辑:,如Riggs所建议的,phpMyAdmin有备份工具,通常可以在主机上使用。

事实上,即使在您的主机上不可用,您仍然可以将其安装在您的http服务器上,并将其配置为访问远程DB服务器:

phpmyadmin

票数 1
EN

Stack Overflow用户

发布于 2013-08-09 12:16:54

如果您有相同的备份问题,无论是使用一些自定义脚本,还是使用诸如"sqlbuddy“之类的工具--那么得出的结论是,问题出在表和/或数据库中。

我将尝试复制有问题的表并备份这些表,而不是原始表,以查看附加内容:

代码语言:javascript
运行
复制
CREATE TABLE etiquetas_copy AS SELECT * FROM etiquetas

如果您不能备份副本,那么我猜行数就是问题所在。有些提供程序是任意的(有时是静默地)杀死使用太多资源的脚本或DB请求。

您可以按照注释中的建议,一次备份1000行。就像这样:

代码语言:javascript
运行
复制
    $result = mysql_query('SELECT * FROM '.$table." LIMIT $n,$n+1000") or die(msyql_error());

您必须将其包装起来,而周围的几行是一个循环,当获取的行数为1000时,它会“转”,以便在处理完这1000行后读取以下批处理。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18000676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档