To be useful, backups must be scheduled regularly. A full backup
        (a snapshot of the data at a point in time) can be done in MySQL
        with several tools. For example, InnoDB Hot
        Backup provides online nonblocking physical backup of
        the InnoDB data files, and
        mysqldump provides online logical backup.
        This discussion uses mysqldump.
      
MySQL Enterprise. For expert advice on backups and replication, subscribe to the MySQL Enterprise Monitor. For more information, see http://www.mysql.com/products/enterprise/advisors.html.
        Assume that we make a full backup of all our
        InnoDB tables in all databases using the
        following command on Sunday at 1 p.m., when load is low:
      
shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql
        The resulting .sql file produced by
        mysqldump contains a set of SQL
        INSERT statements that can be
        used to reload the dumped tables at a later time.
      
        This backup operation acquires a global read lock on all tables
        at the beginning of the dump (using
        FLUSH TABLES WITH READ
        LOCK). As soon as this lock has been acquired, the
        binary log coordinates are read and the lock is released. If
        long updating statements are running when the
        FLUSH statement is issued, the
        backup operation may stall until those statements finish. After
        that, the dump becomes lock-free and does not disturb reads and
        writes on the tables.
      
        It was assumed earlier that the tables to back up are
        InnoDB tables, so
        --single-transaction uses a
        consistent read and guarantees that data seen by
        mysqldump does not change. (Changes made by
        other clients to InnoDB tables are not seen
        by the mysqldump process.) If the backup
        operation includes nontransactional tables, consistency requires
        that they do not change during the backup. For example, for the
        MyISAM tables in the mysql
        database, there must be no administrative changes to MySQL
        accounts during the backup.
      
Full backups are necessary, but it is not always convenient to create them. They produce large backup files and take time to generate. They are not optimal in the sense that each successive full backup includes all data, even that part that has not changed since the previous full backup. It is more efficient to make an initial full backup, and then to make incremental backups. The incremental backups are smaller and take less time to produce. The tradeoff is that, at recovery time, you cannot restore your data just by reloading the full backup. You must also process the incremental backups to recover the incremental changes.
        To make incremental backups, we need to save the incremental
        changes. In MySQL, these changes are represented in the binary
        log, so the MySQL server should always be started with the
        --log-bin option to enable that
        log. With binary logging enabled, the server writes each data
        change into a file while it updates data. Looking at the data
        directory of a MySQL server that was started with the
        --log-bin option and that has
        been running for some days, we find these MySQL binary log
        files:
      
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001 -rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002 -rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003 -rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004 -rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005 -rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006 -rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
        Each time it restarts, the MySQL server creates a new binary log
        file using the next number in the sequence. While the server is
        running, you can also tell it to close the current binary log
        file and begin a new one manually by issuing a
        FLUSH LOGS SQL
        statement or with a mysqladmin flush-logs
        command. mysqldump also has an option to
        flush the logs. The .index file in the data
        directory contains the list of all MySQL binary logs in the
        directory.
      
The MySQL binary logs are important for recovery because they form the set of incremental backups. If you make sure to flush the logs when you make your full backup, the binary log files created afterward contain all the data changes made since the backup. Let's modify the previous mysqldump command a bit so that it flushes the MySQL binary logs at the moment of the full backup, and so that the dump file contains the name of the new current binary log:
shell>mysqldump --single-transaction --flush-logs --master-data=2 \--all-databases > backup_sunday_1_PM.sql
        After executing this command, the data directory contains a new
        binary log file, gbichot2-bin.000007,
        because the --flush-logs
        option causes the server to flush its logs. The
        --master-data option causes
        mysqldump to write binary log information to
        its output, so the resulting .sql dump file
        includes these lines:
      
-- Position to start replication or point-in-time recovery from -- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;
Because the mysqldump command made a full backup, those lines mean two things:
            The dump file contains all changes made before any changes
            written to the gbichot2-bin.000007
            binary log file or newer.
          
            All data changes logged after the backup are not present in
            the dump file, but are present in the
            gbichot2-bin.000007 binary log file or
            newer.
          
        On Monday at 1 p.m., we can create an incremental backup by
        flushing the logs to begin a new binary log file. For example,
        executing a mysqladmin flush-logs command
        creates gbichot2-bin.000008. All changes
        between the Sunday 1 p.m. full backup and Monday 1 p.m. will be
        in the gbichot2-bin.000007 file. This
        incremental backup is important, so it is a good idea to copy it
        to a safe place. (For example, back it up on tape or DVD, or
        copy it to another machine.) On Tuesday at 1 p.m., execute
        another mysqladmin flush-logs command. All
        changes between Monday 1 p.m. and Tuesday 1 p.m. will be in the
        gbichot2-bin.000008 file (which also should
        be copied somewhere safe).
      
The MySQL binary logs take up disk space. To free up space, purge them from time to time. One way to do this is by deleting the binary logs that are no longer needed, such as when we make a full backup:
shell>mysqldump --single-transaction --flush-logs --master-data=2 \--all-databases --delete-master-logs > backup_sunday_1_PM.sql
          Deleting the MySQL binary logs with mysqldump
          --delete-master-logs can be dangerous if your server
          is a replication master server, because slave servers might
          not yet fully have processed the contents of the binary log.
          The description for the PURGE BINARY
          LOGS statement explains what should be verified
          before deleting the MySQL binary logs. See
          Section 12.5.1.1, “PURGE BINARY LOGS Syntax”.
        


User Comments
We had one problem where we had too many bin files. As our database was heavily used the file size was quite big there were too many of them.
Please be sure to have a policy where you remove your old transactional log files as mentioned in the last example.
I could not found the disk pace was mentioned in Binary LOG Manual page.
Here's a scrip i wrote to backup my db, using a user that's not "mysql".
There's an entry in the sudoers file to allow the user to read the log files
The backup (mysql) user has "super,reload,all" privileges + its password in .my.cnf
The backup path is on a NAS filesystem.
What's missing is a function to remove old full backups if needed.
------------------------------------------------------
#!/bin/bash
MODE=$1
MYSQLUSER=backup
BINLOGPATH=/var/log/mysql
BINLOGNAME=mysql-bin
ARCHIVEPATH=/usr/app/security/var/data/backups/mysql/
setRead() {
# change properties on binlog path
sudo chmod o+rx $BINLOGPATH
sudo chmod o+r $BINLOGPATH/*
}
resetRead() {
# restore properties on binlog path
sudo chmod o-r $BINLOGPATH/*
sudo chmod o-rx $BINLOGPATH
}
copyBinlogs() {
# copy binlogs to archive dir
echo "Copying binlogs"
setRead;
for FILE in `cat $BINLOGPATH/$BINLOGNAME.index`
do
SFILE=(${FILE/*\//})
if [ ! -f $ARCHIVEPATH/$SFILE.gz ]
then
echo "- binlog $SFILE"
cp $FILE $ARCHIVEPATH
gzip $ARCHIVEPATH/$SFILE
fi
done
resetRead;
}
saveBinlogs() {
# move latest binlogs to savedir
echo "Saving binlogs"
SAVEDIR=`date +%Y%m%d`
echo $SAVEDIR
mkdir -p $ARCHIVEPATH/$SAVEDIR
mv $ARCHIVEPATH/*.gz $ARCHIVEPATH/$SAVEDIR
}
# --- Main ---
case "$MODE" in
'full')
# Weekly backup
# - copy all bin logs to backup directory
# - clean path of backup directory
echo "Weekly backup"
DATE=`date +%Y%m%d`
mysqldump -u $MYSQLUSER --single-transaction --flush-logs --master-data=2 \
--all-databases --delete-master-logs | gzip > $ARCHIVEPATH/$SAVEDIR/full-$DATE.sql.gz
copyBinlogs;
saveBinlogs;
;;
'incremental')
# Daily backup
# - flush logs
# - copy all bin logs to backup directory if not already done
echo "Mysql daily backup"
mysqladmin -u $MYSQLUSER flush-logs
copyBinlogs;
;;
*)
echo "Usage: mysql_backup [full|incremental]"
;;
esac
------------------------------------------------------
You should never use --delete-master-logs as the warning specifies. The above script is quite dangerous if you have many replication slaves.
A much better alternative is to do
echo 'PURGE MASTER LOGS BEFORE DATE_SUB( NOW( ), INTERVAL 7 DAY);' | /usr/bin/mysql
Regarding copyBinlogs() - it may be wise to preserve the creation and modification times, with 'cp -p', so it is easy to order them correctly when recovering.
further to the comment on delete-master-logs - see
http:://bugs.mysql.com/bug.php?id=24733
In other words, delete-master-logs is bad news for versions before the fix for that bug went in.
Add your own comment.