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.= "nn".$row2[1].";nn"; 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.="nnn"; } 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.= "nn".$row2[1].";nn"; 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,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,$pass); mysql_select_db($base,$link); // Launching the script progress_export( $file,$idField ); 编辑脚本末尾的设置,并针对两个表中的一个运行它. 您应该在脚本仍处理时看到输出,并获取有关正在处理的行的一些引用,如下所示:
如果脚本完成… 那么你将有一个表的备份(小心,我没有测试生成的SQL)! 我猜它不会完成: 如果脚本没有到达第一个“导出行…”调试语句 然后问题是在查询时. 然后,您应该尝试使用偏移量和限制参数来限制查询,继续进行二分法以找出它挂起的位置 生成限制为1000个第一结果的查询的示例. // Launching the script progress_export( $file,1000 ); 如果脚本在挂起之前显示正在导出的某些行 在确定显示的最后一行ID之前,您应该尝试: >再次运行脚本,看它是否挂在同一行.这是为了看看我们是否面临“随机”问题(它从来都不是随机的). 例如50作为偏移量,一些大数字作为限制: // Launching the script progress_export( $file,50,600000 ); 这是为了检查它自己的行是否导致问题,或者它是否是临界行数/数据量… >如果每次都返回相同的最后一行,请检查并给我们反馈. 如果您无法在分配的资源上播放,那么解决方案将是将导出拆分为块. >如果行几乎每次都改变,那就更复杂了…… 一些线索: 我对VPS没有任何经验,但是你对CPU使用有什么限制吗? 如果您一次使用过多的资源,那么您的流程是否会排队? 那些没有问题的转储表怎么样?是否存在与两者一样大的表格导致问题? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |