如何在MySQL中进行备份?

26

如何在MySQL中进行备份?

我希望有比每隔“x”小时运行mysqldump更好的方法。

是否有像SQL Server那样的东西,每天可以进行完全备份,然后每小时进行增量备份,以便如果您的数据库死机,您可以恢复到最新的备份?

类似于DB日志的内容,只要日志没有损坏,您就可以恢复到数据库死亡的精确点吗?

还有,这些操作对锁定会产生什么影响呢? 如果我运行mysqldump,我会预期在线交易会被锁定一段时间。

15个回答

13

11

mysqldump是一个合理的方法,但请注意对于某些引擎来说,这将在备份期间锁定您的表 - 这会对大型生产数据集的可用性产生影响。

另一个明显的选择是使用Maatkit的mk-parallel-dump(http://www.maatkit.org/),如果你是mysql管理员,你真的应该尝试一下。它使用mysqldump并行地转储多个表或数据库,从而减少了转储所需的总时间。

如果您正在运行复制设置(如果您在生产中使用MySQL重要数据,您没有任何不这样做的借口),则从专用于此目的的复制从节点中获取转储将防止任何锁定问题造成麻烦。

在Linux上,下一个明显的选择是使用LVM快照。您可以锁定表,对文件系统进行快照,然后再次解锁表;然后使用该快照的挂载启动额外的MySQL,并从那里转储。该方法在这里描述:http://www.mysqlperformanceblog.com/2006/08/21/using-lvm-for-mysql-backup-and-replication-setup/


7
现在我开始听起来像是这个产品的市场营销人员了。我在这里回答了一个问题,然后我又在这里回答了另一个问题
简而言之,对于你所有的mysql需求,请尝试使用来自webyog的sqlyog(企业版),它不仅可以安排备份,还可以安排同步,因此您实际上可以将数据库复制到远程服务器。
它有一个免费的社区版和一个企业版。我建议您使用后者,但我也建议您先从comm版开始看看是否喜欢它

社区版的链接是:http://code.google.com/p/sqlyog/ - John M
卖给我 :) 我会试一试。我不想要一个带有所有参数和易错性的命令行mysqldump解决方案。MySQL Workbench不提供自动备份(企业版也是如此),不像旧的MySQL Admin,它已经不能为我工作了(备份在中途冻结)。我找不到社区版的任何功能列表,你有吗?我会先试用一下以便了解一下。 - Michael K

4

4

我使用mysqlhotcopy,这是一个用于本地MySQL数据库和表的快速在线热备份工具。我对它感到相当满意。


2
mysqlhotcopy只能用于MyISAM表,不能用于InnoDB。 - Richard H

3
我使用一个简单的脚本将mysql数据库转储到tar.gz文件中,使用gpg加密,并将其发送到邮件帐户(Google Mail,但实际上这并不重要)。
该脚本是一个Python脚本,基本上运行以下命令并通过电子邮件发送输出文件。
mysqldump -u theuser -p mypassword thedatabase | gzip -9 - | gpg -e -r 12345 -r 23456 > 2008_01_02.tar.gz.gpg
这是整个备份。它还有网站备份部分,只需tar/gzip/加密文件即可。它是一个相当小的网站,因此Web备份远远少于20MB,可以轻松发送到GMail帐户(MySQL转储很小,压缩后约300KB)。它非常基本,不会很好地扩展。我每周使用cron运行一次。
不太确定我们应该如何在答案中放置较长的脚本,因此我将其作为代码块插入。
#!/usr/bin/env python
#encoding:utf-8
#
# Creates a GPG encrypted web and database backups, and emails it

import os, sys, time, commands

################################################
### Config

DATE = time.strftime("%Y-%m-%d_%H-%M")

# MySQL login
SQL_USER = "mysqluser"
SQL_PASS = "mysqlpassword"
SQL_DB = "databasename"

# Email addresses
BACKUP_EMAIL=["email1@example.com", "email2@example.com"] # Array of email(s)
FROM_EMAIL = "root@myserver.com" # Only one email

# Temp backup locations
DB_BACKUP="/home/backupuser/db_backup/mysite_db-%(date)s.sql.gz.gpg" % {'date':DATE}
WEB_BACKUP="/home/backupuser/web_backup/mysite_web-%(date)s.tar.gz.gpg" % {'date':DATE}

# Email subjects
DB_EMAIL_SUBJECT="%(date)s/db/mysite" % {'date':DATE}
WEB_EMAIL_SUBJECT="%(date)s/web/mysite" % {'date':DATE}

GPG_RECP = ["MrAdmin","MrOtherAdmin"]
### end Config
################################################

################################################
### Process config
GPG_RECP = " ".join(["-r %s" % (x) for x in GPG_RECP]) # Format GPG_RECP as arg

sql_backup_command = "mysqldump -u %(SQL_USER)s -p%(SQL_PASS)s %(SQL_DB)s | gzip -9 - | gpg -e %(GPG_RECP)s > %(DB_BACKUP)s" % {
    'GPG_RECP':GPG_RECP,
    'DB_BACKUP':DB_BACKUP,
    'SQL_USER':SQL_USER,
    'SQL_PASS':SQL_PASS,
    'SQL_DB':SQL_DB
}

web_backup_command = "cd /var/www/; tar -c mysite.org/ | gzip -9 | gpg -e %(GPG_RECP)s > %(WEB_BACKUP)s" % {
    'GPG_RECP':GPG_RECP,
    'WEB_BACKUP':WEB_BACKUP,
}
# end Process config
################################################

################################################
### Main application
def main():
        """Main backup function"""
        print "Backing commencing at %s" % (DATE)

        # Run commands
        print "Creating db backup..."
        sql_status,sql_cmd_out = commands.getstatusoutput(sql_backup_command)
        if sql_status == 0:
                db_file_size = round(float( os.stat(DB_BACKUP)[6]  ) /1024/1024, 2) # Get file-size in MB
                print "..successful (%.2fMB)" % (db_file_size)
                try:
                    send_mail(
                        send_from = FROM_EMAIL,
                        send_to   = BACKUP_EMAIL,
                        subject   = DB_EMAIL_SUBJECT,
                        text      = "Database backup",
                        files     = [DB_BACKUP],
                        server    = "localhost"
                    )
                    print "Sending db backup successful"
                except Exception,errormsg:
                    print "Sending db backup FAILED. Error was:",errormsg
                #end try

                # Remove backup file
                print "Removing db backup..."
                try:
                        os.remove(DB_BACKUP)
                        print "...successful"
                except Exception, errormsg:
                        print "...FAILED. Error was: %s" % (errormsg)
                #end try
        else:
                print "Creating db backup FAILED. Output was:", sql_cmd_out
        #end if sql_status

        print "Creating web backup..."
        web_status,web_cmd_out = commands.getstatusoutput(web_backup_command)
        if web_status == 0:
                web_file_size = round(float( os.stat(WEB_BACKUP)[6]  ) /1024/1024, 2) # File size in MB
                print "..successful (%.2fMB)" % (web_file_size)
                try:
                    send_mail(
                        send_from = FROM_EMAIL,
                        send_to   = BACKUP_EMAIL,
                        subject   = WEB_EMAIL_SUBJECT,
                        text      = "Website backup",
                        files     = [WEB_BACKUP],
                        server    = "localhost"
                    )
                    print "Sending web backup successful"
                except Exception,errormsg:
                    print "Sending web backup FAIELD. Error was: %s" % (errormsg)
                #end try

                # Remove backup file
                print "Removing web backup..."
                try:
                        os.remove(WEB_BACKUP)
                        print "...successful"
                except Exception, errormsg:
                        print "...FAILED. Error was: %s" % (errormsg)
                #end try
        else:
                print "Creating web backup FAILED. Output was:", web_cmd_out
        #end if web_status
#end main
################################################

################################################
# Send email function

# needed email libs..
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

def send_mail(send_from, send_to, subject, text, files=[], server="localhost"):
        assert type(send_to)==list
        assert type(files)==list

        msg = MIMEMultipart()
        msg['From'] = send_from
        msg['To'] = COMMASPACE.join(send_to)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        msg.attach( MIMEText(text) )

        for f in files:
                part = MIMEBase('application', "octet-stream")
                try:
                    part.set_payload( open(f,"rb").read() )
                except Exception, errormsg:
                    raise IOError("File not found: %s"%(errormsg))
                Encoders.encode_base64(part)
                part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
                msg.attach(part)
    #end for f

        smtp = smtplib.SMTP(server)
        smtp.sendmail(send_from, send_to, msg.as_string())
        smtp.close()
#end send_mail
################################################

if __name__ == '__main__':
        main()

3
你可能需要通过 MySQL 复制来补充你当前的离线备份计划。这样,如果硬件出现故障,你只需更换机器。如果你快速发现了故障,你的用户甚至不会注意到任何停机或数据丢失。

我的网站目前托管在共享主机上 - 复制是我自己需要实现的还是应该联系我的主机提供商? - Ali

2

您可以使用mysqldump命令的"--single-transaction --skip-lock-tables"选项进行InnoDB数据库/表的完整备份,而无需锁定(停机)操作。该方法适用于制作每周快照以及每日/每小时二进制日志增量备份。(#使用二进制日志实现增量备份)。


1

1

@Jake,

感谢提供的信息。 现在看起来只有商业版才有备份功能。

MySQL 中难道没有任何内置的东西可以进行良好的备份吗?

官方 MySQL 页面甚至建议使用诸如“好吧,你可以复制文件,只要它们没有被更新”之类的方法...


复制是否算作备份?下面提到的ibbackup产品似乎是Linux解决方案,没有Windows版本。 - jake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接