To back up and restore your MySQL database, perform these steps:
- Under the commands directory in your project's home directory, create a bash script: backup_mysql_db.sh. Start the script with variable and function definitions, as follows:
/home/myproject/commands/backup_mysql_db.sh
#!/usr/bin/env bash
SECONDS=0
export DJANGO_SETTINGS_MODULE=myproject.settings.production
PROJECT_PATH=/home/myproject
REPOSITORY_PATH=${PROJECT_PATH}/src/myproject
LOG_FILE=${PROJECT_PATH}/logs/backup_mysql_db.log
DAY_OF_THE_WEEK=$(LC_ALL=en_US.UTF-8 date +"%w-%A")
DAILY_BACKUP_PATH=${PROJECT_PATH}/db_backups/${DAY_OF_THE_WEEK}.sql
LATEST_BACKUP_PATH=${PROJECT_PATH}/db_backups/latest.sql
error_counter=0
echoerr() { echo "$@" 1>&2; }
cd ${PROJECT_PATH}
mkdir -p logs
mkdir -p db_backups
source env/bin/activate
cd ${REPOSITORY_PATH}
DATABASE=$(echo "from django.conf import settings; print(settings.DATABASES['default']['NAME'])" | python manage.py shell -i python)
USER=$(echo "from django.conf import settings; print(settings.DATABASES['default']['USER'])" | python manage.py shell -i python)
PASSWORD=$(echo "from django.conf import settings; print(settings.DATABASES['default']['PASSWORD'])" | python manage.py shell -i python)
EXCLUDED_TABLES=(
django_session
)
IGNORED_TABLES_STRING=''
for TABLE in "${EXCLUDED_TABLES[@]}"; do
IGNORED_TABLES_STRING+=" --ignore-table=${DATABASE}.${TABLE}"
done
- Then, add commands to create a dump of the database structure and data:
echo "=== Creating DB Backup ===" > ${LOG_FILE}
date >> ${LOG_FILE}
echo "- Dump structure" >> ${LOG_FILE}
mysqldump -u "${USER}" -p"${PASSWORD}" --single-transaction --no-data "${DATABASE}" > "${DAILY_BACKUP_PATH}" 2>> ${LOG_FILE}
function_exit_code=$?
if [[ $function_exit_code -ne 0 ]]; then
{
echoerr "Command mysqldump for dumping database structure
failed with exit code ($function_exit_code)."
error_counter=$((error_counter + 1))
} >> "${LOG_FILE}" 2>&1
fi
echo "- Dump content" >> ${LOG_FILE}
# shellcheck disable=SC2086
mysqldump -u "${USER}" -p"${PASSWORD}" "${DATABASE}" ${IGNORED_TABLES_STRING} >> "${DAILY_BACKUP_PATH}" 2>> ${LOG_FILE}
function_exit_code=$?
if [[ $function_exit_code -ne 0 ]]; then
{
echoerr "Command mysqldump for dumping database content
failed with exit code ($function_exit_code)."
error_counter=$((error_counter + 1))
} >> "${LOG_FILE}" 2>&1
fi
- Add commands to compress the database dump and to create a symbolic link, latest.sql.gz:
echo "- Create a *.gz archive" >> ${LOG_FILE}
gzip --force "${DAILY_BACKUP_PATH}"
function_exit_code=$?
if [[ $function_exit_code -ne 0 ]]; then
{
echoerr "Command gzip failed with exit code
($function_exit_code)."
error_counter=$((error_counter + 1))
} >> "${LOG_FILE}" 2>&1
fi
echo "- Create a symlink latest.sql.gz" >> ${LOG_FILE}
if [ -e "${LATEST_BACKUP_PATH}.gz" ]; then
rm "${LATEST_BACKUP_PATH}.gz"
fi
ln -s "${DAILY_BACKUP_PATH}.gz" "${LATEST_BACKUP_PATH}.gz"
function_exit_code=$?
if [[ $function_exit_code -ne 0 ]]; then
{
echoerr "Command ln failed with exit code
($function_exit_code)."
error_counter=$((error_counter + 1))
} >> "${LOG_FILE}" 2>&1
fi
- Finalize the script by logging the time taken to execute the previous commands:
duration=$SECONDS
echo "------------------------------------------" >> ${LOG_FILE}
echo "The operation took $((duration / 60)) minutes and $((duration % 60)) seconds." >> ${LOG_FILE}
exit $error_counter
- In the same directory, create a bash script, restore_mysql_db.sh, with the following content:
# home/myproject/commands/restore_mysql_db.sh
#!/usr/bin/env bash
SECONDS=0
PROJECT_PATH=/home/myproject
REPOSITORY_PATH=${PROJECT_PATH}/src/myproject
LATEST_BACKUP_PATH=${PROJECT_PATH}/db_backups/latest.sql
export DJANGO_SETTINGS_MODULE=myproject.settings.production
cd "${PROJECT_PATH}"
source env/bin/activate
echo "=== Restoring DB from a Backup ==="
echo "- Fill the database with schema and data"
cd "${REPOSITORY_PATH}"
zcat "${LATEST_BACKUP_PATH}.gz" | python manage.py dbshell
duration=$SECONDS
echo "------------------------------------------"
echo "The operation took $((duration / 60)) minutes and $((duration % 60)) seconds."
- Make both scripts executable:
$ chmod +x *.sh
- Run the database backup script:
$ ./backup_mysql_db.sh
- Run the database restoration script (with caution if in production):
$ ./restore_mysql_db.sh