Skip to content

Commit

Permalink
feat(mysql): tokudb备份恢复修复 #8451
Browse files Browse the repository at this point in the history
  • Loading branch information
seanlook committed Dec 11, 2024
1 parent 3784316 commit 4419039
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ func (c *Component) GenerateBackupConfig() error {
cst.DbbackupGoInstallPath,
fmt.Sprintf("dbbackup.%d.ini", port),
)

dailyBackupConfigFile, err := ini.LoadSources(ini.LoadOptions{
PreserveSurroundedQuote: true,
IgnoreInlineComment: true,
Expand All @@ -137,6 +136,10 @@ func (c *Component) GenerateBackupConfig() error {
logger.Error("map %s to struct failed: %s", dailyBackupConfigPath, err.Error())
return err
}
if backupConfig.Public.EncryptOpt == nil {
// 避免 reflect: call of reflect.Value.Type on zero Value
backupConfig.Public.EncryptOpt = &cmutil.EncryptOpt{}
}

backupConfig.Public.BackupType = c.Params.BackupType
backupConfig.Public.BackupTimeOut = ""
Expand Down Expand Up @@ -185,7 +188,6 @@ func (c *Component) GenerateBackupConfig() error {
logger.Error("mkdir %s failed: %s", backupConfig.Public.BackupDir, err.Error())
return err
}

}
// 增加为tbinlogdumper做库表备份的日志输出,保存流程上下文
c.backupDir = backupConfig.Public.BackupDir
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func migrateOld(cmd *cobra.Command, args []string) (errs error) {
if indexFilePath, indexContent, err := backupexe.MigrateInstanceBackupInfo(infoFilePath, &cnf); err != nil {
//errMsg := fmt.Sprintf("failed migrate backup info port %d\n: %s", cnf.Public.MysqlPort, err.Error())
//errs = errors2.Join(errs, errors.New(errMsg))
fmt.Println(err)
continue
} else {
fmt.Println("migrate infoFile", infoFilePath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ sub tmysql_version_parser {
mkdir("$backdir/mysql_data");
mkdir("$backdir/tokudb_data");
mkdir("$backdir/tokudb_log");
mkdir("$backdir/innodb_data");

if ($sock =~ /.+\/(\d+)\// ) {
$port = $1;
Expand All @@ -64,35 +65,50 @@ sub tmysql_version_parser {
my $data_dir = undef;
my $tokudb_data_dir = undef;
my $tokudb_log_dir = undef;
my $innodb_home_dir = undef;
my $innodb_log_dir = undef;
my $myconf = ($port == 3306)? "/etc/my.cnf" : "/etc/my.cnf.$port";

open( my $my_cnf_fp, "< $myconf" ) or die "$myconf open error" ;
while ( my $line = <$my_cnf_fp> ) {
chomp $line;
if ( not defined $data_dir ) {
if ( $line =~ /\s*datadir\s*=([\S]+)/ ) {
if ( $line =~ /\s*datadir\s*=\s*([\S]+)/ ) {
$data_dir = $1;
next;
}
}
if ( not defined $tokudb_data_dir ) {
if ( $line =~ /\s*tokudb_data_dir\s*=([\S]+)/ ) {
if ( $line =~ /\s*tokudb_data_dir\s*=\s*([\S]+)/ ) {
$tokudb_data_dir = $1;
next;
}
}
if ( not defined $tokudb_log_dir ) {
if ( $line =~ /\s*tokudb_log_dir\s*=([\S]+)/ ) {
if ( $line =~ /\s*tokudb_log_dir\s*=\s*([\S]+)/ ) {
$tokudb_log_dir = $1;
next;
}
}
if ( not defined $innodb_home_dir ) {
if ( $line =~ /\s*innodb_data_home_dir\s*=\s*([\S]+)/ ) {
$innodb_home_dir = $1;
next;
}
}
if ( not defined $innodb_log_dir ) {
if ( $line =~ /\s*innodb_log_group_home_dir\s*=\s*([\S]+)/ ) {
$innodb_log_dir = $1;
next;
}
}
}
close($my_cnf_fp);

unless (defined $data_dir &&
defined $tokudb_data_dir &&
defined $tokudb_log_dir )
defined $tokudb_log_dir &&
defined $innodb_home_dir )
{
die "some key in $myconf lost";
}
Expand All @@ -112,7 +128,7 @@ sub tmysql_version_parser {
my $tname=( split(/\//,$ARGV[0]) )[-1];
my $dir;
if($ARGV[0] =~ /(.+)\/${tname}$/){
$dir=$1;
$dir=$1;
}else{
die "failed while parsing backdir";
}
Expand Down Expand Up @@ -152,17 +168,17 @@ sub tmysql_version_parser {
print $debug_log "get metadata lock ok\n\n";
}

my @white_databases=qw(information_schema db_infobase mysql performance_schema test sys);
my @white_databases=qw(information_schema db_infobase mysql performance_schema test sys infodba_schema);
my @backup_databases;
my @other_engines;
eval{
local $SIG{__DIE__} = "";
local $SIG{__DIE__} = "";
$sql="show databases";
my $select=$dbh->prepare($sql);
$select->execute();
while(my $result=($select->fetchrow_array)[0]){
if(not grep(/$result/,@white_databases)){
push(@backup_databases,$result);
push(@backup_databases,$result);
}
}
if(@backup_databases){
Expand All @@ -173,7 +189,7 @@ sub tmysql_version_parser {
while(my @row_array=$select->fetchrow_array){
my ($engine)=@row_array;
if(not $engine eq 'TokuDB'){
push(@other_engines,$engine);
push(@other_engines,$engine);
}
}
}
Expand All @@ -184,7 +200,7 @@ sub tmysql_version_parser {


my $metadata_before_backup=qx(ls -l $data_dir $tokudb_log_dir/*);
##### STEP 3. get checkpoint lock
##### STEP 3. get checkpoint lock
#set tokudb_checkpoint_lock=on:let dml only change redo log
$row_ref=$dbh->selectrow_arrayref("select * from information_schema.global_variables where variable_name='tokudb_checkpoint_lock'");
print $debug_log "global:$row_ref->[0]:$row_ref->[1]\n";
Expand All @@ -199,7 +215,7 @@ sub tmysql_version_parser {
print $debug_log "set tokudb_checkpoint_lock=on ok\n\n";


##### STEP 4. Copy tokudb.* and redo log, and get binlog position in a blocking-binlog or stopping-slave;
##### STEP 4. Copy tokudb.* and redo log, and get binlog position in a blocking-binlog or stopping-slave;
if(defined $dump_slave){
$dbh->do("set \@old_rpl_stop_slave_timeout=\@\@rpl_stop_slave_timeout;") or die("failed to get the value of rpl_stop_slave_timeout");
print($debug_log "rpl_stop_slave_timeout:".(($dbh->selectrow_arrayref("select \@\@rpl_stop_slave_timeout"))->[0])."\n");
Expand All @@ -216,7 +232,7 @@ sub tmysql_version_parser {
system("rm -rf $backdir/mysql_data")==0 or die "failed:$!";
close $debug_log;
close $backed_debug_log;
exit(223);
exit(223);
}
print $debug_log qx(date);
print $debug_log "stop slave ok\n\n";
Expand Down Expand Up @@ -249,7 +265,7 @@ sub tmysql_version_parser {
$select_file->execute();
while(my @tokudb_files=$select_file->fetchrow_array){
push(@tokudb_data_files,$tokudb_files[0]);
printf(FILELIST "$tokudb_files[0]\n");
printf(FILELIST "$tokudb_files[0]\n");
}
close FILELIST;

Expand Down Expand Up @@ -294,21 +310,28 @@ sub tmysql_version_parser {


##### STEP 5. Copy frm
## no flush table with read lock ???
print $debug_log qx(date);
print $debug_log "copy mysql data dir: $data_dir/ ...";
system("ls $data_dir| xargs -I '{}' cp -r $data_dir/{} $backdir/mysql_data")==0 or die "failed:$!";

print $debug_log qx(date);
print $debug_log "copy innodb ibdata1 in: $innodb_home_dir ...";
system("cp -r $innodb_home_dir $backdir/innodb_data/")==0 or die "failed:$!\n";
system("cp -r $innodb_log_dir $backdir/innodb_data/")==0 or die "failed:$!\n";

print $debug_log "\tdone.\n";
print $debug_log qx(date)."\n";

##### STEP 6. recovery tokudb_commit_sync;
##### STEP 6. recovery tokudb_commit_sync;
#$ret=$dbh->do("set global tokudb_commit_sync=$old_global_tokudb_commit_sync");
#die "unable to restore tokudb_commit_sync" if not defined $ret or $ret<0;
##sleep(100);
#print qx(date);
#print "enable tokudb redo log buffer ok\n\n";
#
#goto SKIP;
##### STEP 7. copy data or increment data
##### STEP 7. copy data or increment data
if(is_low_space("$Bin/history_backup_size","$Bin/last_backup_size",$backdir,0.96,$debug_log)){
push(@tokudb_backup_warnings,"SMS#low space,previous file for port:${port} will be deleted,and a fully backup will be done today");
#delete old file
Expand Down Expand Up @@ -341,7 +364,7 @@ sub tmysql_version_parser {
opendir (DIR,$dir) or die "can't open the directory $dir";
my @dirs=readdir DIR;
close DIR;

#my $fully_backup_port=$wday;
#while($fully_backup_port<$port){$fully_backup_port+=7;}
#my $days_since_fully=$fully_backup_port-$port;
Expand All @@ -355,7 +378,7 @@ sub tmysql_version_parser {
my $i;
my $fully_stamp_and_name={};
for($i=0;$i<7;$i++){
my $fullyday=strftime("%Y%m%d", localtime($fully_stamp-$i*24*3600));
my $fullyday=strftime("%Y%m%d", localtime($fully_stamp-$i*24*3600));
#print "\$port:$port \$fully_backup_port:$fully_backup_port \$days_since_fully:$days_since_fully \$fullyday:$fullyday\n";
#print "now begin to exam ".(scalar @dirs)." file\n";
foreach my $file(@dirs){
Expand All @@ -375,7 +398,7 @@ sub tmysql_version_parser {
}
close INFO;
if(defined $tmpstamp and defined $tmpname and $tmpname eq $current_name){#find fully backup info file
$fully_stamp_and_name->{$tmpstamp}=$tmpname;
$fully_stamp_and_name->{$tmpstamp}=$tmpname;
}
$tmpstamp=undef;
$tmpname=undef;#for multi fully backup one day
Expand All @@ -398,7 +421,7 @@ sub tmysql_version_parser {
system("cp $tokudb_data_dir/$file $backdir/tokudb_data") ==0 or die "failed:$!";
#printf("copied $file\n");
}
}
}
}else{ #previous backup failed
#print "\tfully backup(i:$i fully_stamp:$fully_stamp)";
print $backed_debug_log "\ttmpstamp:$tmpstamp" if defined $tmpstamp;
Expand All @@ -414,7 +437,7 @@ sub tmysql_version_parser {
print $debug_log "\tdone.\n";
print $debug_log qx(date)."\n";

##### STEP 8. check file change time
##### STEP 8. check file change time
my $metadata_after_backup=qx(ls -l $data_dir $tokudb_log_dir/*);
print $backed_debug_log "############################################# metadata before backup ######################################################\n";
print $backed_debug_log $metadata_before_backup;
Expand Down Expand Up @@ -449,15 +472,15 @@ sub tmysql_version_parser {
}
}

##### STEP 9. release metadata lock
##### STEP 9. release metadata lock
if($tmysql_ver ge tmysql_version_parser("tmysql-2.1.3")){
$dbh->do("unlock tables") or die "failed to release metadata lock";
print $debug_log qx(date);
print $debug_log "release all metadata lock ok\n\n";
}


##### STEP 10. release tokudb_checkpoint_lock
##### STEP 10. release tokudb_checkpoint_lock
$dbh->do("SET TOKUDB_CHECKPOINT_LOCK=OFF") or die "release tokudb checkpoint lock failed";
$row_ref=$dbh->selectrow_arrayref("select * from information_schema.global_variables where variable_name='tokudb_checkpoint_lock'");
print $debug_log "global:$row_ref->[0]:$row_ref->[1]\n";
Expand All @@ -468,9 +491,9 @@ sub tmysql_version_parser {
$dbh->disconnect;


##### STEP 11. fully backup info to file
##### STEP 11. fully backup info to file
#save fully backup info to file
open my $latest_fully_backup_info,">$Bin/latest_fully_backup_info.$port"
open my $latest_fully_backup_info,">$Bin/latest_fully_backup_info.$port"
or die("ERROR: Can not open latest fully backup info file $Bin/latest_fully_backup_info.$port for $@");
printf $latest_fully_backup_info "FULLY_STAMP=$fully_stamp\n";
printf $latest_fully_backup_info "FULLY_NAME=$fully_name\n";
Expand Down Expand Up @@ -542,12 +565,12 @@ sub is_low_space{
my $space_may_used=$disk_used+$max;
my $warn_level=$disk_total*$max_percent;
print $debug_log "total-space:${disk_total}B used-space:${disk_used}B backup-may-use:${max}B warn-level:${warn_level}B \n";
if($space_may_used>$warn_level){
if($space_may_used>$warn_level){
print $debug_log "use-space + space-backup-may-use=${space_may_used}B > warn_level=${warn_level}B\n";
return 1;
}else{
print $debug_log "use-space + space-backup-may-use=${space_may_used}B <= warn_level=${warn_level}B\n";
return 0;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
my $myconf = undef;
my $increment=0;

my @normal_dbs = ("mysql", "test", "performance_schema", "db_infobase", "sys");
# this database will not copy from backup to target, so the target instance innodb ibdata1 cannot be copied too
#my @normal_dbs = ("test", "db_infobase");
my @normal_dbs = ("mysql", "test", "performance_schema", "sys", "db_infobase", "infodba_schema");

Getopt::Long::Configure ("bundling_override");
GetOptions(
Expand All @@ -39,6 +41,7 @@
my $data_dir = undef;
my $tokudb_data_dir = undef;
my $tokudb_log_dir = undef;
my $innodb_home_dir = undef;

open( my $my_cnf_fp, "< $myconf" ) or die "$myconf open error" ;
while ( my $line = <$my_cnf_fp> ) {
Expand All @@ -61,6 +64,12 @@
next;
}
}
if ( not defined $innodb_home_dir ) {
if ( $line =~ /\s*innodb_data_home_dir\s*=\s*([\S]+)/ ) {
$innodb_home_dir = $1;
next;
}
}
}
close($my_cnf_fp);

Expand All @@ -71,6 +80,7 @@
die "some key in $myconf lost";
}

print "copy tokudb_log to $tokudb_log_dir ...\n";
system("ls $backdir/tokudb_log|xargs -I '{}' cp -r $backdir/tokudb_log/{} $tokudb_log_dir") == 0 or die "failed";
if($increment){
if(!open FILELIST,"<$backdir/tokudb_data/filelist.txt"){
Expand All @@ -87,14 +97,39 @@
system("cp $file $tokudb_data_dir") == 0 or die "failed";
}
}else{
print "copy tokudb_data to $tokudb_data_dir ...\n";
eval{system("ls $backdir/tokudb_data |xargs -I '{}' cp -r $backdir/tokudb_data/{} $tokudb_data_dir")}; die $@ if $@;
}
system("ls $backdir/tokudb.*|xargs -I '{}' cp {} $data_dir") == 0 or die "failed";

foreach my $file (glob("$backdir/mysql_data/*/")){
my $tmp_file=basename($file);
if(not grep(/$tmp_file/,@normal_dbs) ){
print "copy database: $tmp_file\n";
print "copy mysql_data/ database: $tmp_file\n";
system("cp -r $file $data_dir") == 0 or die "failed";
}
}

# ibdata1: /data1/mysqldata/20000/innodb/data/ibdata1
# innodb_home_dir: /data1/mysqldata/20000/innodb/data
# innodb_data: /data1/mysqldata/20000/innodb
# if innodb/data/ibdata1 not exists, try to copy from backup
my $innodb_data = dirname($innodb_home_dir);
unless (-e "$innodb_home_dir/ibdata1") {
print "copy innodb_data: from $backdir/innodb_data/* to $innodb_data \n";
unless (-e "$backdir/innodb_data") {
die "lost innodb_data $innodb_home_dir/ibdata1";
}
mkdir("$innodb_data");
system("ls $backdir/innodb_data/ |xargs -I '{}' cp -r $backdir/innodb_data/{} $innodb_data") == 0 or die "failed";

foreach my $file (glob("$backdir/mysql_data/*/")){
my $tmp_file=basename($file);
if(grep(/$tmp_file/,@normal_dbs) ){
print "copy mysql_data/ database: $tmp_file\n";
system("cp -r $file $data_dir") == 0 or die "failed";
}
}
} else {
print "no need to copy innodb_data because $innodb_home_dir/ibdata1 already exists\n";
}
Loading

0 comments on commit 4419039

Please sign in to comment.