Skip to content

Instantly share code, notes, and snippets.

@zetas
Last active March 8, 2022 19:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zetas/01d0559ca2fb9392d67e to your computer and use it in GitHub Desktop.
Save zetas/01d0559ca2fb9392d67e to your computer and use it in GitHub Desktop.
Incremental DB Backup Scripts
<?php
/**
* Incremental DB Backup Script.
*
* Requires: innobackupex percona script.
*
* Meant to run via cron, every 8 hours. It assumes during the fourth
* invocation a day has gone by.
*
* @author Kingcat <kingcat@nzb.cat>
* @last_modified 3/19/2016
*
* @notes This script has no deps on nZEDb so it can be placed anywhere.
*/
/**
* Inside this directory it will create the base backup in the ./base directory,
* the first incremental in the ./hourly.1 directory and so forth until ./hourly.3.
* At that point it will rotate the backups, applying all incrementals to the base,
* tarring and gzipping the base directory, deleting the base and all the incrementals,
* and rerunning the base backup for the next iteration.
*/
$backup_home = '/path/to/backups';
//Below here not much needs to be modified, you may want to modify the "--parallel=4" flag
// if your hardware can't afford to run 4 threads during backup.
class DBBackup {
public $backup_home;
public $base_dir;
public $cmd = 'innobackupex';
public $flags = [
'basic' => '--parallel=4 --rsync',
'no_ts' => '--no-timestamp',
'incremental' => '--incremental',
'inc_basedir' => '--incremental-basedir=',
'inc_dir' => '--incremental-dir=',
'apply' => '--apply-log',
'redo' => '--redo-only'
];
const CLEANUP_DAYS = 7;
public function __construct($backup_dir, $base_dir) {
if (is_writable($backup_dir)) {
$this->backup_home = $backup_dir;
} else {
throw new InvalidArgumentException();
}
$this->base_dir = $base_dir;
}
public function prepareBackup($dir, $incremental=true, $redo_only=true) {
$cmd = sprintf('%s %s', $this->cmd, $this->flags['apply']);
if ($redo_only)
$cmd .= sprintf(' %s', $this->flags['redo']);
if ($incremental) {
$cmd .= sprintf(' %s %s%s', $this->base_dir,$this->flags['inc_dir'],$dir);
} else {
$cmd .= sprintf(' %s', $dir);
}
system($cmd, $return);
return $return;
}
public function rotateBackup($inc_dirs) {
$date = date('omd-His');
$rotate_file = sprintf('%s/%s.tar.gz', $this->backup_home, $date);
$rotate_cmd = sprintf('cd %s && tar -czf %s ./', $this->base_dir, $rotate_file);
system($rotate_cmd, $return);
if ($return == 0) {
foreach ($inc_dirs as $dir) {
$rm_cmd = sprintf('rm -fr %s', $dir);
system($rm_cmd);
}
system("rm -fr $this->base_dir");
} else {
throw new ErrorException('unable to rotate');
}
}
public function incrementalBackup($basedir, $destdir) {
$cmd = sprintf('%s %s %s %s %s %s%s',
$this->cmd,
$this->flags['basic'],
$this->flags['no_ts'],
$this->flags['incremental'],
$destdir,
$this->flags['inc_basedir'],
$basedir
);
system($cmd, $return);
if ($return != 0)
throw new ErrorException('unable to complete incremental backup');
}
public function doBaseBackup() {
$cmd = sprintf('%s %s %s %s',
$this->cmd,
$this->flags['basic'],
$this->flags['no_ts'],
$this->base_dir);
system($cmd, $return);
if ($return != 0)
throw new ErrorException('unable to complete base backup');
}
public function cleanUp() {
$cmd = sprintf("find %s -name '*.tar.gz' -mtime +%s -delete",
$this->backup_home,
self::CLEANUP_DAYS);
system($cmd, $return);
if ($return != 0)
throw new ErrorException('unable to cleanup backup dir');
}
}
$fourth_backup_dir = sprintf('%s/hourly.3', $backup_home);
$third_backup_dir = sprintf('%s/hourly.2', $backup_home);
$second_backup_dir = sprintf('%s/hourly.1', $backup_home);
$first_backup_dir = sprintf('%s/base', $backup_home);
$backup = new DBBackup($backup_home, $first_backup_dir);
if (file_exists($fourth_backup_dir)) {
if ($backup->prepareBackup($first_backup_dir, false) == 0)
if ($backup->prepareBackup($second_backup_dir) == 0)
if ($backup->prepareBackup($third_backup_dir) == 0)
if ($backup->prepareBackup($fourth_backup_dir, true, false) == 0)
if ($backup->prepareBackup($first_backup_dir, false, false) ==0)
$backup->rotateBackup([$second_backup_dir, $third_backup_dir, $fourth_backup_dir]);
echo "Rotate complete";
}
if (file_exists($third_backup_dir)) {
$backup->incrementalBackup($third_backup_dir, $fourth_backup_dir);
echo "Third incremental backup complete";
exit;
}
if (file_exists($second_backup_dir)) {
$backup->incrementalBackup($second_backup_dir, $third_backup_dir);
echo "Second incremental backup complete";
exit;
}
if (file_exists($first_backup_dir)) {
$backup->incrementalBackup($first_backup_dir, $second_backup_dir);
$backup->cleanUp();
echo "First incremental backup complete";
exit;
}
$backup->doBaseBackup();
echo "Base backup complete";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment