在Git中备份MySQL数据库是一个好主意吗?


57

我正在尝试改善应用程序的备份情况。我有一个Django应用程序和MySQL数据库。我读了一篇文章,建议在Git中备份数据库。

一方面,我喜欢它,因为它将使数据和代码的副本保持同步。

但是Git是为代码而不是数据而设计的。因此,它会做很多额外的工作来使MySQL每次提交都转储,这并不是必须的。如果我在存储文件之前先对其进行压缩,那么git还会对文件进行区分吗?

(转储文件当前未压缩为100MB,压缩后为5.7MB。)

编辑:代码和数据库模式定义已经在Git中了,它确实是我现在担心备份的数据。


13
如果您的公司有一个IT(运营)部门,那么他们应该负责处理。
迈克尔·汉普顿

1
是应用程序的数据部分,还是通过应用程序创建的内容?
温斯顿·埃韦特2014年

1
当您运行时,Git会尝试对所有文件进行差异化git gc(或者它是底层文件git repack;根据可配置的默认设置,git偶尔会自动运行它)。它还将始终缩小它们,因此实际上存储它们未压缩可能会更好。
Jan Hudec

1
它是哪种数据库:是生产数据库还是开发数据库?
el.pescado 2014年

Answers:


101

在丢失任何数据之前,让我尝试介绍该问题的系统管理员观点。

我们创建备份的原因只有一个:使发生错误时能够恢复,并且总是会恢复。因此,适当的备份系统的要求远远超出git可以合理处理的范围。

以下是尝试在git中备份数据库时可以预见的一些问题:

  • 每次“备份”时,存储库都会急剧增长。由于git存储了整个对象(虽然已压缩),然后又将它们扩散(例如,当您运行git gc,并永久保留历史记录,所以您将存储大量不需要或什至不需要的数据。您可能需要限制为节省磁盘空间或出于法律原因而执行的备份的数量或保留期限,但是很难在不造成大量附带损害的情况下从git repo 删除旧修订
  • 还原仅限于您存储在存储库中的时间点,并且由于数据如此之大,因此回溯到不多的时间可能会很慢。为此目的而设计的备份系统可以限制存储的数据量,同时可能提供更大的粒度,并提供更快的还原速度,从而减少灾难发生时的停机时间。支持数据库的备份解决方案(示例)还可以提供连续备份,以确保不会丢失单个事务。
  • 提交也可能会变慢,并且随着数据库的增长而变慢。请记住,git本质上是映射到文件系统的键值数据存储,因此受基础文件系统的性能特征的影响。该时间长度可能最终超过备份间隔,到那时您将无法再满足SLA。适当的备份系统还可以随着数据的增长而花费更长的时间进行备份,但是备份的时间并不是那么快,因为它们会根据您配置的保留策略自动管理自己的大小。

尽管事实上如果将数据库转储放入git中,显然可以做一些有趣的事情,但总的来说,我不建议出于保留备份的目的而进行转储。尤其是由于备份系统广泛可用(许多备份系统甚至是开源的),并且在确保数据安全并使其能够尽快恢复的方面表现得更好。


这是最好的答案,因为Michael涵盖了一致性问题。根据数据库的大小和使用情况,快照无法在给定的时间点可靠地复制数据,并且您可能会遇到约束问题。复制可能是您要研究的东西-dev.mysql.com/doc/refman/5.0/en/replication.html
Aaron Newton

4
这不仅是最佳答案,而且是唯一答案。通常,您是一名开发人员,因此备份不是您的事。其他人已经(或应该)已经在照顾他们,如果您开始参与进来,则可能会干扰已经正常运行的系统。这些盒子应该已经被备份了,所以您将拥有一个备份,一个自己的备份以及一个自己的备份的备份,而且它们的大小都在不断增加。那就疯了。加:您是一名开发人员:为什么您(可能)仍要靠近生产箱?
Maximus Minimus 2014年

2
@JimmyShelter有一种流派,认为DevOps并不意味着Dev和Ops紧密合作,而是Dev实际上 Ops。它通常不能很好地工作,但这并不能阻止人们尝试它。
迈克尔·汉普顿

这应该是公认的答案。它清楚地说明了备份系统的要求和目的,然后说明git如何不合适。用于讨论一致性和性能的额外奖励积分。
加布里埃尔·鲍曼

让我说一下,我假设OP没有任何可以为他处理此问题的运营团队,就发布了我的答案。我同意您的看法,这类任务最好留给实际正在运行该系统并了解其解决方法的人员。但是在某些情况下,您不得不戴上不完全属于您的帽子,我相信在这种情况下,尝试学习一些最佳实践比仅提出自己的人为解决方案更好。我不得不说我也发现您的回答很有启发性!
logc 2014年

39

我的两分钱:我认为这不是一个好主意。GIT做类似“在不同的时间点存储一组文件的快照”之类的事情,因此您可以完美地使用GIT之类的东西,但这并不意味着您应该这样做。GIT旨在存储源代码,因此您将缺少其大部分功能,而为了一点方便,您将要牺牲很多性能。

让我假设您考虑此问题的主要原因是“保持数据和代码的同步副本”,这意味着您担心代码的2.0版需要与1.0版不同的数据库架构。 。一个更简单的解决方案是将数据库模式(作为带有CREATE语句的SQL脚本集)与源代码一起存储在Git存储库中。然后,安装过程的一部分将是在以前安装的数据库服务器上执行这些脚本。

这些-d表的实际内容CREATE与源代码的版本无关。想象一下,您在服务器A和服务器B上安装了版本1.0的软件,这些文件在不同公司的不同团队中使用。几周后,即使架构完全相同,表的内容也会有很大不同。

由于您要备份数据库的内容,因此建议您使用一个备份脚本,该脚本用该转储所属的软件的当前版本标记该备份转储。该脚本应位于GIT存储库中(以便它可以访问源代码版本字符串),但是转储本身不属于版本控制系统。

编辑

阅读激发问题原始帖子之后,我发现这是一个更加可疑的想法。关键是该mysqldump命令将数据库的当前状态转换为一系列SQL INSERT语句,GIT可以对它们进行比较以仅获取更新的表行。

mysqldump部分很合理,因为这是MySQL文档中列出的备份方法之一。GIT部分是作者未能注意到数据库服务器保留事务日志以便从崩溃中恢复的地方,包括MySQL。它使用此日志,不GIT,你应该为你的数据库的增量备份。首先,最重要的是,您可以在恢复后旋转或刷新日志,而不是将GIT信息库膨胀到无限甚至更大的优点。


2
我不确定在没有版本控制中的数据的情况下存储数据库模式是否有意义。数据是最重要的,这就是我要备份的内容。我喜欢用当前软件版本标记数据库备份的想法。我将尝试实现类似的方法。
wobbily_col 2014年

10
在没有数据的情况下存储架构的要点是,在安装后,您的软件应“准备使用”。如果它是Wiki,则应该可以开始创建Wiki页面并将某些内容写入其中。如果安装模式内容,则安装后Wiki已经充满了X Wiki页面。这不完全是“安装Wiki系统以编写我们的内容”,而是“从某处复制Wiki以读取它”。 。
logc 2014年

3
根据您所处的实际情况修改您的问题可能是一个好主意。即使您不能发布所有详细信息,也要声明您需要大量数据才能在每次安装中均保持不变,这一点很重要,或者有一个单一的安装...
logc 2014年

2
@wobbily_col基于非文本的二进制格式在源代码管理的上下文中具有有限的值。您无法对其进行差异化,也无法进行分支 / 合并等。因此,尽管您当然可以使用git来存储数据库,但大多数人还是喜欢对数据库结构以及必要的数据进行脚本编写。这是一个折衷方案,需要更多工作,但要提供以上功能列表。您必须权衡这是否是解决方案的好主意。否则,您可能可以让GIT直接存储数据库,但这并不完全适合该任务。
丹尼尔·B

3
@RaduMurzea:我认为这是一个原则问题。版本控制系统旨在管理源代码,而不是二进制文件。这不是大小的问题。不,数据库转储不应该签入到存储库中,就像培训视频都不应该签入一样。但是没有人阻止您这样做。:)
logc

7

就个人而言,我认为使用源代码控制版本系统存储备份文件不是一个好主意,因为GIT版本控制是针对数据文件而不是二进制文件或MySQL备份转储文件之类的转储文件设计的。您可以做到这一点并不意味着您应该自动做到。而且,您的存储库(考虑到每个新提交的新数据库备份)将大大增加,并占用大量硬盘空间,并且GIT的性能将受到影响,从而导致源代码控制系统运行缓慢。对我来说,执行备份策略并在代码出现问题时需要还原数据库时始终准备好备份文件是很好的,但是并没有使用源代码控制工具来存储二进制数据。

由于这些原因,在第1天和第2天存储备份文件,然后看到两个备份文件之间的差异时,我看不到任何实用程序。这将需要大量额外且无用的工作。提交新代码时,不要使用GIT来存储数据库备份,而是将数据库备份存储在以日期和时间分隔的不同路径中,并在代码中使用标记插入为每个版本创建的新数据库备份的一些引用,正如有人已经建议的那样。

关于数据库备份和GIT的最后一点:数据库管理员在由于某些数据丢失而需要还原数据库时,不需要检查第一天的备份文件和第二天的备份文件之间的差异,他只需要知道哪个是最后一个备份文件,使他可以还原数据库,而不会发生任何错误和数据丢失,从而减少了停机时间。确实,数据库管理员的任务是在系统由于某些原因发生故障时尽快使数据可用于恢复。如果将数据库备份存储在与提交相关联的GIT中,则不允许数据库管理员快速还原数据,因为备份仅限于存储在GIT存储库中的时间点,并且减少了停机时间系统的

然后,我不建议使用存储GIT的备份,而不是使用一个良好的备份软件解决方案(也有一些人在这里),这将提供更多的粒度和将让你保持你的数据安全,安全,让您的发生灾难时,数据恢复简单快捷。


也许downvoter将解释为什么他/她downvoted ..
阿尔贝托·索拉诺

1
不是下注者,但我认为这种方法引入了一个永远存在的合并冲突,这特别不利于大多数git用户喜欢的经常分支,经常合并的工作流程。
丹尼尔·B

@DanielB我建议不要使用版本控制系统来存储数据库备份文件。我认为不使用任何版本控制系统就可以轻松解决数据库备份问题。版本控制系统(GIT,TFS,SVN等)是为软件而不是转储文件或数据库备份或仅用于存储数据而设计的(有很多解决方案)。
阿尔贝托·索拉诺

我认为大多数用户会阅读前几句话并投下反对票,因为您似乎会说可以使用。

1
@AlbertoSolano我明白了;但是先阅读问题(“我可以在GIT中备份数据库吗?”),然后阅读第一条语句(“可以存储备份文件...”),似乎您在说相反的话。答案的其余部分似乎都在说它不在这里或那里,而我怀疑大多数人认为这是一场火车事故。
丹尼尔·B

1

您不应该将二进制数据存储在Git中,尤其是数据库中。
代码更改和数据库DML更改完全不同。

MySQL和Oracle可以编写存档日志,以将其还原到任何时间点。只要将这些日志备份到安全的地方,就可以了。

使用Git备份这些“归档日志”没有任何意义。生产环境中的存档日志相当繁重,应在进行常规完整备份后将其删除。将它们放在git中也是没有用的-从某种意义上讲,它们已经是存储库。


1
为什么不使用Git备份MySQL创建的这些“归档日志”?
t 2014年

1
仅仅因为这没有道理。生产环境中的存档日志相当繁重,应在进行常规完整备份后将其删除。将它们放在git中也是没有用的-从某种意义上讲,它们已经是存储库。迈克尔·汉普顿(Michael Hampton)在此问题上给出了一个很好的答案(在本页上)。
Jehy,2014年

1
如果要在git中保留所有内容的副本,为什么还要麻烦旋转日志?最好只保留一个怪物日志文件。
wobbily_col 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.