一个关于文本备份数据库的算法问题

renqiang_888 2009-04-07 11:41:05
insert into tableName values("a","c",....);
insert into tableName values("1","b",....);
..............
..............
.............


最近在写用php备份数据库到文本的程序,还原的时候,遇到一个难题如上的文字是存储在文档当中的字符串,每个insert语句是一行,
大约有十万行吧,我现在页面当中用php脚本读取文本文件,一次读取前100行插入所要还原的表当中,然后使用重新定向再次执行这个页面(为的是不到于长时间执行脚本使页面超时),但是重新执行脚本的时候,再读取文本的前100行还是刚才插入的前100行数据,但是在第一次执行时又没有办法把读取出来的100条数据删除掉或者做一个标记(当然作标记可以把整个文本读取出来再删除10行之后,再写入数据,但是数据量太大,行不通),请问一下有什么好的算法或者办法没有啊?
...全文
184 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
renqiang_888 2009-04-08
  • 打赏
  • 举报
回复
谢谢楼上了,我只想一个我提出问题的思路和,谢谢。
digihero 2009-04-08
  • 打赏
  • 举报
回复
现在各种程序都有分卷备份。甚至还有帝国备份这种专门备份数据库的东西存在。

像phpwind,discuz等都有分卷备份,甚至以16进制的方式进行备份再恢复以防止中文和特殊符号出错。

你可以参考一下discuz
renqiang_888 2009-04-08
  • 打赏
  • 举报
回复
楼上的朋友说的有道理,其实是可以分卷来处理的,但一个文本文件当中到少也得有1000条数据吧,
如果每次读取100条之后,插入数据库,再重新定向当前页面,应当如何做标记呢?
意思是下次读取第200-300条数据。
应该网 2009-04-08
  • 打赏
  • 举报
回复
文本不适合大量数据的操作吧。10万行记录不少了

进来学习……
renqiang_888 2009-04-08
  • 打赏
  • 举报
回复
谢谢了,还想请问一个问题,
就是用txt备份数据库的话,一般的情况下每个文本存储的数量大小不超过多少KB为最好呢?
如果超过了就分卷处理,谢谢了
程序猿之殇 2009-04-08
  • 打赏
  • 举报
回复
1fgets函数每次获取一行数据,所以需要读取100次.
2不需要记录开始行,只需要记录上次结束的位置就可以了.
 上次结束的位置可以用ftell函数来获取.


$findex = isset($_GET['findex']) ? $_GET['findex'] : 0;

$fp = fopen('xxxx.sql', 'r');
$i = 0;
fseek($fp, $findex);
while(!feof($fp) && $i++< 100)
{
$fdata = fgets($fp);
$findex = ftell($fp);
//echo $i . ":" . $data . "<br/>";
}

//记录findex以便下次读取
renqiang_888 2009-04-08
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 yctin 的回复:]
十万行不是很多...直接一次完成吧

每做完一定行数用 set_time_limit() 防止超时就可以了
还可以用 ob_start() , ob_flush() 输出进度


但要注意防止重复执行~影响效率
[/Quote]

如果指针位置此时等于10万的话,
用fseek()定位也是很慢啊?
frederic_zhao 2009-04-08
  • 打赏
  • 举报
回复
顶5楼第4个方法~
carpenter01 2009-04-08
  • 打赏
  • 举报
回复
用 BCP 先插到一个临时表里 之后在整理
这样效率会高一些
seaprince 2009-04-08
  • 打赏
  • 举报
回复
至于怎么按行处理,可以参考linux tail的算法,几天前模拟了一个:http://bbs3.chinaunix.net/thread-1421500-1-1.html
renqiang_888 2009-04-08
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 runffer_yang 的回复:]
方法很多
1. 建个标记文件表示要restore了,然后crontab去读这个文件,调用batch,删除标记文件.
2. 主程序用Ajax调用别的PHP去执行,给两个参数:从哪行读,读多少行.
3. 和1差不多,调用外部程序,不必等返回值.
///////////////如果你非常BT地钟情于用纯PHP来处理////////////////
4. hoge.php:

PHP code<?php
$start = $_GET['start_line'] || 0;
settype($start,"integer");
$game_over = false;
/*
从文件的$st…
[/Quote]
谢谢您的回答,您的第四种方法说:
/*
从文件的$start行开始处理100条记录,
到文件尾的话结束,设$game_over为true
*/

但不知道如何从$start行开始处理100条数据?
如何文本当中有1000条数据的话,那么如何想得到第200-300条之间的数据,是不是还要先读取前100条数据?
seaprince 2009-04-08
  • 打赏
  • 举报
回复
大文件操作可以考虑一下ftell, fseek 这些函数,操作超大文件都没有问题。
比如你先读100行,ftell得到当前的位置并保存,然后处理。
下次处理时,fseek到上次的位置,继续往下读。
这样的方法非常高效,不会因为文件太大而影响效率。

大文件操作慢主要慢在两个地方:
1:全部读取,明显非常耗内存。
2:遍历,比如读100行,丢弃,再读下一百行,依此类推。此法要遍历整个文件,也是很慢。

fseek, ftell这种方法没有上述问题。
yctin 2009-04-08
  • 打赏
  • 举报
回复
十万行不是很多...直接一次完成吧

每做完一定行数用 set_time_limit() 防止超时就可以了
还可以用 ob_start() , ob_flush() 输出进度


但要注意防止重复执行~影响效率
lonelyriver 2009-04-08
  • 打赏
  • 举报
回复
……
Steve 2009-04-08
  • 打赏
  • 举报
回复
faint,php连接字符串用.
Steve 2009-04-08
  • 打赏
  • 举报
回复
方法很多
1. 建个标记文件表示要restore了,然后crontab去读这个文件,调用batch,删除标记文件.
2. 主程序用Ajax调用别的PHP去执行,给两个参数:从哪行读,读多少行.
3. 和1差不多,调用外部程序,不必等返回值.
///////////////如果你非常BT地钟情于用纯PHP来处理////////////////
4. hoge.php:
<?php
$start = $_GET['start_line'] || 0;
settype($start,"integer");
$game_over = false;
/*
从文件的$start行开始处理100条记录,
到文件尾的话结束,设$game_over为true
*/
if (!$game_over) {
header("location:./hoge.php?start_line?start="+($start+100));
} else {
echo "Game Over.";
}
?>


5. 对4的改进,每次从$start行开始,要空读100行,越到后面效率越低.
如果每一行的大小是确定的,
那么直接算出文件偏移指针用fseek函数移动之.

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧