我有一个巨大的 MySQL 备份文件(来自 mysqldump),其中的表按字母顺序排列。我的恢复失败了,我想从备份文件中的下一个表继续上次中断的位置。(我已经更正了这个问题,这实际上不是关于 MySQL 恢复等的问题。)
我想要做的是获取我的备份文件,例如backup.sql
并修剪文件的开头,直到我看到以下行:
-- Table structure for `mytable`
然后,之后的所有内容都会出现在我的结果文件中,例如backup-secondhalf.sql
。由于文件是 bzip2 压缩的,这有点复杂,但这应该不是什么大问题。
我想我可以这样做:
$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Table structure for table `mytable`' -m 1
这将为我提供我想要修剪的文件中的字节偏移量取决于。 然后:
$ bunzip2 -c backup.sql.bz2 | dd skip=[number from above] | bzip2 -c > backup-secondhalf.sql.bz2
不幸的是,这需要我对文件运行两次 bunzip2 并读取所有这些字节两次。
有没有办法一次性完成这一切?
我不确定我的 sed-fu 是否足够强大,可以执行“删除所有行直到正则表达式,然后让文件的其余部分通过”的表达式。
这是在 Debian Linux 上,所以我有可用的 GNU 工具。
答案1
bunzip2 -c backup.sql.bz2 | \
sed -n '/-- Table structure for `mytable`/,$p'
解释:
-n suppress automatic printing of pattern space
地址范围构造:以正则表达式开始
/-- Table structure for `mytable`/
结尾
$ Match the last line.
命令
p Print the current pattern space.
编辑:取决于你如何转储数据库,你可能有非常长行。GNU sed 可以处理这些行,直到可用内存量达到最大值。
答案2
注意:不是实际答案
因为我有动力解决这个问题现在之后,我继续grep
查找我想要的文件中的偏移量;效果很好。
不幸的是,运行dd
需要您设置ibs=1
,这基本上意味着没有缓冲,而且性能很糟糕。在等待 dd 完成时,我花了一些时间编写自己的定制 C 程序来跳过字节。完成之后,我发现这tail
对我来说同样容易:
$ bunzip2 -c restore.sql.bz2 | tail -c +[offset] | bzip2 -c > restore-trimmed.sql.bz2
我说“这没有回答我的问题”是因为它仍然需要两次传递文件:一次是找到我正在寻找的东西的偏移量,另一次是修剪文件。
如果我回到我的自定义程序,我可以实现一个钾通道蛋白在程序的“只读”阶段,然后切换到“读取+写入所有内容”。
答案3
我想知道这样的事情是否能起到作用:
use strict;
use warnings;
use feature 'say';
use IO::Uncompress::Bunzip2 '$Bunzip2Error';
my $file = $ARGV[0] // die "need a file";
my $zh = IO::Uncompress::Bunzip2->new( $file, {
AutoClose => 1,
Transparent => 1,
} ) or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";
my $trigger = undef;
while ( <$zh> ) {
chomp;
$trigger = 1 if $_ eq '-- Dumping data for table `experiments`';
say if $trigger;
}
因此基本上它会按照模式开始打印内容,也可以将其直接传输到 bzip2/gzip,就像在 Debian 上perl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2
需要的那样。libio-compress-perl