ML
    • Recent
    • Categories
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Anyone used percona-xtrabackup?

    IT Discussion
    percona xtrabackup mysql mariadb
    2
    10
    1.7k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • AmbarishrhA
      Ambarishrh
      last edited by

      Thinking of replacing automysql backup with xtrabackup

      https://www.percona.com/software/mysql-database/percona-xtrabackup/feature-comparison

      1 Reply Last reply Reply Quote 1
      • scottalanmillerS
        scottalanmiller
        last edited by

        We used it at Change when I was there.

        1 Reply Last reply Reply Quote 0
        • AmbarishrhA
          Ambarishrh
          last edited by

          And how was the experience, is it good? I will be testing this but would like to hear from ML

          1 Reply Last reply Reply Quote 0
          • AmbarishrhA
            Ambarishrh
            last edited by

            @Reid-Cooper i've seen on another post that you've been using Percona backup, Could you please share some feedback on this?

            1 Reply Last reply Reply Quote 0
            • AmbarishrhA
              Ambarishrh
              last edited by scottalanmiller

              I got a script for Xtrabackup but need some help in breaking it down and understand it well to customise it to our requirements or tweak if necessary

              #!/bin/bash
              
              while [ ${#} -gt 0 ]
              do
                  a=${1}
                  shift
                  case "${a}" in
                      --socket)
                          socket=${1}
                          shift
                          ;;
                      --data)
                          data=${1}
                          shift
                          ;;
                      --dest)
                          dest=${1}
                          shift
                          ;;
                      --days)
                          days=${1}
                          shift
                          ;;
                      --months)
                          months=${1}
                          shift
                          ;;
                      --noslave)
                          noslave=1
                          shift
                          ;;
                      --nolock)
                          nolock="--no-lock"
                          shift
                          ;;
                  esac
              done
              
              if [[ ! $socket || ! $data || ! $dest || ! $days ]]; then
               echo "Usage:"
               echo "  $0 --socket /tmp/mysql.sock --data /var/lib/mysql --dest /home/backup --days 7 [--months 2] [--noslave] [--nolock]"
               exit 1
              elif [[ ! -S $socket ]]; then
               echo "Error, $socket is not a valid socket";
               exit 1;
              elif [[ ! -f ${data}/ibdata1 ]]; then
               echo "Error, $data does not appear to be a valid data directory";
               exit 1;
              elif [[ ! -d ${dest} ]]; then
               echo "Error, $dest does not appear to be a valid target directory";
               exit 1;
              elif [[ ! $days -gt 0 ]]; then
               echo "Error, $days is not a valid number of days";
               exit 1
              fi;
              
              error() {
                  echo -e "$1"
                  cat ${log}
                  exit 1
              }
              
              # Probably don't want to change these
              ts=$(date +%Y-%m-%d)
              target=${dest}/${ts}
              cnf=${dest}/my.cnf
              log=${dest}/backup.log
              
              echo "Starting backup job - $(date)" > $log
              cd ${dest}
              
              # If it's the beginning of the month, drop the day off
              if [[ $months -gt 0 ]] && [[ "$(date +%d)" == "01" ]]; then
                      target=${dest}/${ts}
              fi;
              
              # Check we've got sufficient disk space for a copy of $data
              dbsize=$(du -ks ${data} 2> /dev/null | awk '{print $1}')
              free=$(df -kP ${dest} | tail -n1 | awk '{print $4}')
              if [[ $free -lt $dbsize ]]; then
                  error "Insufficient disk space free for backup, ${dbsize}k required but only only ${free}k avail"
              fi;
              
              # Make sure slave is running
              if [[ $noslave -ne 1 ]]; then
                  slave=$(mysql --socket ${socket} --host=localhost -e 'show slave status \G'  | egrep -c '(Slave_IO_Running|Slave_SQL_Running): Yes')
                  if [[ $slave -ne 2 ]]; then
                      error "Slave is not running"
                  fi;
              fi;
              
              # Build the my.cnf for xtrabackup
              cat /etc/mysql/my.cnf > $cnf
              cat /root/.my.cnf >> $cnf
              echo "[xtrabackup]" >> $cnf
              echo "datadir = ${data}" >> $cnf
              echo "target_dir = ${dest}/" >> $cnf
              
              # Run the actual backup
              innobackupex --defaults-file=${cnf} --socket=${socket} --no-timestamp --slave-info $target --host=localhost ${nolock} >> ${dest}/backup.log 2>&1
              err=$?
              echo ERR CODE $err >> $log
              if [[ $err -ne 0 ]]; then error "Innobackupex backup returned ${err}, backup failed"; fi;
              
              # Apply the transaction logs so it's consistent
              innobackupex --socket=${socket} --apply-log $target --host=localhost >> ${dest}/backup.log 2>&1
              err=$?
              echo ERR CODE $err >> ${dest}/backup.log
              if [[ $err -ne 0 ]]; then error "Innobackupex log apply returned ${err}, backup failed"; fi;
              
              err=0
              
              # Double check we've got frm files for each IBD/MYI
              for x in $(find ${target} -type f -name '*.ibd' -o -name '*.MYI' | grep -v FTS); do
                  b=$(echo $x | cut -d. -f-1)
                  if [[ ! -e ${b}.frm ]]; then
                      echo "$x exists but no ${b}.frm, backup failed";
                      err=1
                  fi;
              done;
              
              # Double check all the databases were copied
              for x in $(find ${data} -mindepth 1 -maxdepth 1 -type d); do
                  db=`basename $x`;
                  if [[ ! -e ${target}/${db} ]]; then
                      error "Database $db is missing from target, backup failed"
                      err=1
                  fi;
              done;
              
              if [[ $err -ne 0 ]]; then error "Sanity checks failed, aborting backup"; fi;
              
              # Create the startup script
              cat > ${target}/start.sh <<EOF
              #!/bin/bash
              
              p=\`dirname \$0\`
              if [[ \$p == "." ]]; then p=\`pwd\`; fi;
              
              if [[ ! -e \${p}/ibdata1 ]]; then
                  echo "This script does not appear to be in a proper mysql data directory"
                  exit 1
              fi;
              
              if [[ \$# -ne 1 ]]; then
                  echo "Unable to start mysql, you must provide a tcp/ip port to listen on"
                  echo "IE: \$0 \$\$"
                  exit 1
              fi;
              
              port=\$1
              
              if [[ ! "\$port" =~ ^[0-9]{4,5}\$ ]]; then
                 echo "Invalid port \$port, expecting a 4-5 digit number"
                 exit 1
              fi
              
              echo
              echo Spawning mysql for \$p using port \${port} and socket /tmp/mysql.sock.\${port}
              echo Connect: mysql --socket=/tmp/mysql.sock.\${port} --host=localhost
              echo Shutdown: mysqladmin shutdown --socket=/tmp/mysql.sock.\${port} --host=localhost
              echo
              
              chown -R mysql:mysql \$p
              /usr/bin/mysqld_safe --pid-file=\${p}/mysql.pid --datadir=\${p} --basedir=/usr --port=\${port} --socket=/tmp/mysql.sock.\${port} --plugin-load=innodb=ha_innodb_plugin.so
              EOF
              
              # Copy the log into the target, tarball it and clean up
              cp ${log} ${target}
              cd ${dest}
              chmod 700 ${target}/start.sh
              chmod 700 ${target}
              tar zcvf ${ts}.tgz ${ts} > /dev/null 2>&1 
              if [[ $? -ne 0 ]]; then
                  error "Tar failed to complete"
              fi;
              rm -rf ${target}
              
              # Double check the tarball has some size to it
              if [[ $(du -ks ${target}.tgz | awk '{print $1}') -lt 10000 ]]; then
                      error "Backup ${target}.tgz is unusually small, backup probably failed"
              fi;
              
              # Setup the latest symlink
              rm -f ${dest}/latest.tgz
              ln -s ${ts}.tgz ${dest}/latest.tgz
              
              # Remove old backups
              ls -rt ${dest}/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].tgz 2> /dev/null | head -n-${days} | xargs rm -f
              ls -rt ${dest}/[0-9][0-9][0-9][0-9]-[0-9][0-9].tgz 2> /dev/null | head -n-${months} | xargs rm -f
              
              # Cleanup
              rm -f ${dest}/stderr ${dest}/stdout ${dest}/my.cnf
              
              echo "Done backup job - $(date)" >> $log
              
              1 Reply Last reply Reply Quote 0
              • scottalanmillerS
                scottalanmiller
                last edited by

                You need to mark it as code when you post a script. Otherwise it's a mess.

                AmbarishrhA 1 Reply Last reply Reply Quote 1
                • AmbarishrhA
                  Ambarishrh @scottalanmiller
                  last edited by

                  @scottalanmiller said:

                  You need to mark it as code when you post a script. Otherwise it's a mess.

                  was wondering how this is done! 🙂

                  1 Reply Last reply Reply Quote 0
                  • AmbarishrhA
                    Ambarishrh
                    last edited by

                    So what does this first block means:

                    while [ ${#} -gt 0 ]
                    do
                        a=${1}
                        shift
                        case "${a}" in
                            --socket)
                                socket=${1}
                                shift
                                ;;
                            --data)
                                data=${1}
                                shift
                                ;;
                            --dest)
                                dest=${1}
                                shift
                                ;;
                            --days)
                                days=${1}
                                shift
                                ;;
                            --months)
                                months=${1}
                                shift
                                ;;
                            --noslave)
                                noslave=1
                                shift
                                ;;
                            --nolock)
                                nolock="--no-lock"
                                shift
                                ;;
                        esac
                    done
                    
                    scottalanmillerS 1 Reply Last reply Reply Quote 0
                    • scottalanmillerS
                      scottalanmiller @Ambarishrh
                      last edited by

                      @Ambarishrh That first block is where it is sifting through the command line arguments parsing out which flags have been passed so that it can set the settings for the rest of the script.

                      scottalanmillerS 1 Reply Last reply Reply Quote 1
                      • scottalanmillerS
                        scottalanmiller @scottalanmiller
                        last edited by

                        So for example, if it detects that you passed the --socket flag if would hit that condition and then look for the ${1} which would be the following parameter and sets the socket variable to that value and tells it to move on or shift to the next argument and continue the loop.

                        1 Reply Last reply Reply Quote 2
                        • 1 / 1
                        • First post
                          Last post