如何在MySQL中进行备份?
如何在MySQL中进行备份?
我希望会比每隔" x"小时运行一次mysqldump更好。
是否有类似SQL Server的功能,我们可以在其中每天进行一次完整备份,然后每小时进行一次增量备份,因此,如果数据库死了,我们可以还原到最新的备份吗?
诸如数据库日志之类的东西,只要日志不死,我们就可以恢复到数据库死亡的确切位置?
另外,这些东西如何影响锁定?
如果我执行mysqldump,我希望在线交易会被锁定一段时间。
解决方案
回答
我们可能需要查看增量备份。
回答
现在,我开始听起来像是该产品的市场营销人员。我在这里回答了一个问题,然后在这里再次回答了另一个问题。
简而言之,请尝试从webyog尝试sqlyog(针对企业)来满足所有mysql要求。它不仅可以安排备份,还可以安排同步,因此我们实际上可以将数据库复制到远程服务器。
它具有免费的社区版和企业版。我向我们推荐稍后的版本,尽管我也建议我们从comm版本开始,然后首先查看喜好。
回答
@Hyman
谢谢(你的)信息。
现在,看起来只有商业版本具有备份功能。
MySQL中没有内置任何功能来进行像样的备份吗?
MySQL官方页面甚至建议诸如"好吧,只要它们没有被更新,就可以复制文件"之类的东西。
回答
我使用mysqlhotcopy,这是用于本地MySQL数据库和表的快速在线热备份实用程序。我对此很满意。
回答
我们可能想用MySQL复制来补充当前的离线备份方案。
然后,如果我们遇到硬件故障,则可以交换计算机。如果我们迅速发现故障,用户甚至不会注意到任何停机时间或者数据丢失。
回答
直接备份mysql数据库文件夹的问题是,备份不一定是一致的,除非我们在备份期间进行了写锁定。
我运行一个遍历所有数据库的脚本,在每个数据库上执行mysqldump和gzip到备份文件夹,然后将该文件夹备份到磁带。
但是,这意味着不存在增量备份之类的事情,因为每晚转储是完整的转储。但是我认为这可能是一件好事,因为与从增量备份还原相比,从完全备份还原的过程要快得多,并且如果要备份到磁带,则可能意味着必须先收集许多磁带。进行完全还原。
无论如何,无论我们采用哪种备份计划,都请确保进行一次试还原以确保其有效,并了解其可能需要花费多长时间以及确切地需要执行哪些步骤。
回答
我使用一个简单的脚本将mysql数据库转储到tar.gz文件中,使用gpg对其进行加密并将其发送到一个邮件帐户(Google Mail,但这确实无关紧要)
该脚本是Python脚本,它基本上运行以下命令,并通过电子邮件发送输出文件。
mysqldump -u theuser -p mypassword数据库| gzip -9 | gpg -e -r 12345 -r 23456> 2008_01_02.tar.gz.gpg
这是整个备份。它还具有Web备份部分,仅tar / gzips /对文件进行加密。这是一个相当小的站点,因此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=["[email protected]", "[email protected]"] # Array of email(s) FROM_EMAIL = "[email protected]" # 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()
回答
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/
回答
运行mysql服务器的增量或者连续备份的正确方法是使用二进制日志。
首先,锁定所有表或者关闭服务器。使用mysql dump进行备份,或者仅复制数据目录。我们只需执行一次,或者在任何时候进行完整备份。
在备份服务器之前,请确保已启用二进制日志记录。
要进行增量备份,请登录服务器并发出FLUSH LOGS命令。然后备份最近关闭的二进制日志文件。
如果我们拥有所有的innodb表,则使用带有--single-transaction选项的inno热备份(不是免费的)或者mysqldump更为简单(我们最好有很多内存来处理事务)。
回答
二进制日志可能是进行增量备份的正确方法,但是如果我们不信任永久存储的二进制文件格式,则可以使用ASCII方式进行增量备份。
mysqldump的格式不是很差,主要问题是它把一张表输出为一行。以下琐碎的sed将沿着记录边界分割其输出:
mysqldump --opt -p | sed -e" s /,(/,\ n(/ g"> database.dump
生成的文件对diff非常友好,并且我已经相当成功地将它们保存在标准SVN存储库中。如果我们发现上一个版本令人厌烦并且需要上周的版本,则还可以保留备份的历史记录。
回答
@丹尼尔
如果我们仍然感兴趣,可以使用Paul Galbraith共享的一种新颖(对我来说是新的)解决方案,该工具允许从oracle在线备份称为ibbackup的innodb表,并引用Paul,
when used in conjunction with innobackup, has worked great in creating a nightly backup, with no downtime during the backup
可以在Paul的博客上找到更多详细信息
回答
我们可以通过带有" --single-transaction --skip-lock-tables"选项的mysqldump进行InnoDB数据库/表的完全转储,而无需锁定(停机)。非常适合用于制作每周快照+每日/每小时二进制日志增量(#使用二进制日志启用增量备份)。
回答
听起来我们正在谈论事务回滚。
因此,就需求而言,如果日志包含所有历史查询,那么这还不是备份吗?为什么需要增量备份,它基本上是数据库日志中所有信息的冗余副本?
如果是这样,为什么不只使用mysqldump并每隔一段时间做一次备份呢?
回答
Percona的家伙对innobackup做了一个开源的替代...
Xtrabackup
https://launchpad.net/percona-xtrabackup/
阅读有关XtraDB的文章
http://www.linux-mag.com/cache/7356/1.html
回答
对于Linux Shell,这是一个非常可靠的解决方案。我已经使用多年了:
http://sourceforge.net/projects/automysqlbackup/
- 是否进行滚动备份:每天,每月,每年
- 很多选择