How I Backup and Restore Large Database on Odoo

Odoo has a fairly easy to use database backup and restore functionality. Previously I had no problem with the database backup and restore job. Before this come. A project with a very large database with size more than 3 GB, and still growing. Last time I check the database size is over 6 GB.

I intend to backup the database from server A which is big, and restore it to server B. I don’t know what the cause is whether my internet is slow or the server configuration are not quite right. The backup process often fails midway. Or it works but the backup result can’t be restored on server B.

Finally I had to modify the odoo’s backup and restore functionality a little, and thank God it worked. Here’s what I did. May be useful for you.

Backup Process

Before start, please see the default route or controller of backup functionality in /web/controllers/main.py file below.

@http.route('/web/database/backup', type='http', auth="none", methods=['POST'], csrf=False)
def backup(self, master_pwd, name, backup_format = 'zip'):
    try:
        odoo.service.db.check_super(master_pwd)
        ts = datetime.datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S")
        filename = "%s_%s.%s" % (name, ts, backup_format)
        headers = [
            ('Content-Type', 'application/octet-stream; charset=binary'),
            ('Content-Disposition', content_disposition(filename)),
        ]
        dump_stream = odoo.service.db.dump_db(name, None, backup_format)
        response = werkzeug.wrappers.Response(dump_stream, headers=headers, direct_passthrough=True)
        return response
    except Exception as e:
        _logger.exception('Database.backup')
        error = "Database backup error: %s" % (str(e) or repr(e))
        return self._render_template(error=error)

From the route or controller above, I copy it, and make a small change, so the accepted method is GET instead of POST. I hope, I can use the wget command from the server B, so i can backup the database that exist in server A directly from server B and save the result directly in server B, without using the odoo’s default backup and restore user interface, so I don’t need to save the backup result in my computer and upload it to server B. Here is the route or controller that I added.

@http.route('/web/database/backup-custom', type='http', auth="none", methods=['GET'], csrf=False)
def backup_custom(self, master_pwd, name, backup_format = 'zip'):
    try:
        odoo.service.db.check_super(master_pwd)
        ts = datetime.datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S")
        filename = "%s_%s.%s" % (name, ts, backup_format)
        headers = [
            ('Content-Type', 'application/octet-stream; charset=binary'),
            ('Content-Disposition', content_disposition(filename)),
        ]
        dump_stream = odoo.service.db.dump_db(name, None, backup_format)
        response = werkzeug.wrappers.Response(dump_stream, headers=headers, direct_passthrough=True)
        return response
    except Exception as e:
        _logger.exception('Database.backup')
        error = "Database backup error: %s" % (str(e) or repr(e))
        return self._render_template(error=error)

After I add the code above on server A, immediately I restart the odoo service. Then on server B via ssh, I enter the /home/ubuntu/backup directory which I meant to save the backup result from server A. You can choose another directory if you want. Then run this command on server B terminal.

wget -O test.zip "http://33.33.33.33:8069/web/database/backup-custom?master_pwd=admin&name=test&backup_format=zip"

The meaning of the code above is to backup the database with the name of “test” on server A (IP 33.33.33.33) and save it as a “test.zip” file on server B. Assuming the odoo master password on server A is “admin” and with a zip backup format. After the process is complete the backup file will be saved in /home/ubuntu/bakcup/test.zip on server B.

If the database size is a bit bigger so it take a longer time and make a wget timeout error, usually I add the timeout option in the wget command and execute the backup command in server A instead of server B. Once the backup process is finished, I send the backup result to server B with sftp command. This is how I execute backup process in server A with timeout option.

wget -T 10800 -O test.zip "http://127.0.0.1:8069/web/database/backup-custom?master_pwd=admin&name=test&backup_format=zip"

With the -T 10800 option above, wget will raise timeout error after 3 hours. You can change the value in seconds.

Restore Process

Please see the odoo default route or controller of restore functionality below

@http.route('/web/database/restore', type='http', auth="none", methods=['POST'], csrf=False)
def restore(self, master_pwd, backup_file, name, copy=False):
    try:
        data_file = None
        db.check_super(master_pwd)
        with tempfile.NamedTemporaryFile(delete=False) as data_file:
            backup_file.save(data_file)
        db.restore_db(name, data_file.name, str2bool(copy))
        return http.local_redirect('/web/database/manager')
    except Exception as e:
        error = "Database restore error: %s" % (str(e) or repr(e))
        return self._render_template(error=error)
    finally:
        if data_file:
            os.unlink(data_file.name)

From the code above, we can see that the method accepted by the restore function is a POST. And the backup_file that we send via the user interface will be saved as a temporary file and will be deleted when the restore process is complete. This is the new restore functionality that I Add on server B.

@http.route('/web/database/restore-custom', type='http', auth="none", methods=['GET'], csrf=False)
def restore_custom(self, master_pwd, backup_file, name, copy=False):
    try:
        data_file = None
        db.check_super(master_pwd)
        db.restore_db(name, backup_file, str2bool(copy))
        return http.local_redirect('/web/database/manager')
    except Exception as e:
        error = "Database restore error: %s" % (str(e) or repr(e))
        return self._render_template(error=error)
    finally:
        if data_file:
            os.unlink(data_file.name)

From the additional restore functionality above, we don’t need to send the backup file to server B and also don’t need to save it as a temporary file because the file is already on server B. Remember we have backed up the database from server A and stored it in the /home/ubuntu/backup directory. We just need to supply the backup_file parameter with the full path of the zipped backup file on server B, for example /home/ubuntu/backup/test.zip. Then after restarting the odoo service on server B, I run the following command to start the restore process.

wget "http://44.44.44.44:8069/web/database/restore-custom?master_pwd=admin&backup_file=%2Fhome%2Fubuntu%2Fbackup%2Ftest.zip&name=test_restore& copy=true"

The meaning of the code above is to restore the /home/ubuntu/backup/test.zip file on server B (IP 44.44.44.44) into a new database with the name test_restore.

After the process is complete a new database with the name of test_restore will appear on server B odoo instalation.

This is how I backup and restore a large database on odoo. If you have any other way please tell me how you did it in the comment section. Thank you.

Related Article

2 Replies to “How I Backup and Restore Large Database on Odoo”

  1. This was awesome. Thanks for sharing, I’m learning so much from your blog. Greetings from Argentina.
    It would be awesome to have any source of notifications to check new posts.

Leave a Reply