使用Git跟踪mysql架构 - 一些问题

时间:2011-04-01 20:14:01

标签: mysql git

如果推荐这个?

我可以问一些关于如何跟踪mysql schema版本的git命令示例吗?

我们是否应该使用另一个存储库,而不是我们通常在应用程序根目录中使用的存储库?

我应该使用名为hook的东西吗?

更新

1)我们导航到.git数据库所在的项目根目录。

2)我们创建了一个名为hooks的子文件夹。

3)我们在这个名为db-commit:

的文件中放了这样的东西
   #!/bin/sh
   mysqldump -u DBUSER -pDBPASSWORD  DATABASE --no-data=true> SQLVersionControl/vc.sql
   git add SQLVersionControl/vc.sql
   exit 0

现在我们可以:

4) git commit -m

此提交将包含一个在提交之前运行的mysql架构转储。

上面的来源是: http://edmondscommerce.github.io/git/using-git-to-track-db-schema-changes-with-git-hook.html

如果这是一种可以接受的方式,我可以请耐心的人逐行评论并尽可能详细地评论这里发生的事情:

#!/bin/sh
mysqldump -u DBUSER -pDBPASSWORD  DATABASE --no-data=true> SQLVersionControl/vc.sql
git add SQLVersionControl/vc.sql
exit 0

非常感谢。

8 个答案:

答案 0 :(得分:23)

假设您已经有一个git repo,请在shell脚本或其他任何内容中执行以下操作:

#!/bin/bash -e
# -e means exit if any command fails
DBHOST=dbhost.yourdomain.com
DBUSER=dbuser
DBPASS=dbpass # do this in a more secure fashion
DBNAME=dbname
GITREPO=/path/to/git/repo
cd $GITREPO
mysqldump -h $DBHOST -u $DBUSER -p$DBPASS -d $DBNAME > $GITREPO/schema.sql # the -d flag means "no data"
git add schema.sql
git commit -m "$DBNAME schema version $(`date`)"
git push # assuming you have a remote to push to

然后每天从一个cron作业开始这个脚本或者你有什么。

编辑:通过在$ gitdir / hooks / pre -commit中放置一个脚本(名称很重要),脚本将在每次提交之前执行。这样,每次提交都会捕获数据库模式的状态,这是有道理的。如果你每次提交时都自动运行这个sql脚本,你就会把你的数据库搞得一团糟,这是没有意义的。

#!/bin/sh

此行指定它是一个shell脚本。

mysqldump -u DBUSER -pDBPASSWORD  DATABASE --no-data=true> SQLVersionControl/vc.sql

这与我上面的答案相同;仅从数据库中获取DDL并将其存储在文件中。

git add SQLVersionControl/vc.sql

这会将SQL文件添加到对存储库进行的每次提交。

exit 0

这会成功退出脚本。这可能很危险。如果mysqldumpgit add失败,您可能会想要保留一些内容。

答案 1 :(得分:9)

如果您只是跟踪架构,请将所有CREATE语句放入一个.sql文件中,然后将该文件添加到git中。

$> mkdir myschema && cd myschema
$> git init
$> echo "CREATE TABLE ..." > schema.sql
$> git add schema.sql
$> git commit -m "Initial import"

答案 2 :(得分:3)

IMO最佳方法如下所述:http://viget.com/extend/backup-your-database-in-git。为了您的方便,我在这里重复最重要的部分。

诀窍是使用mysqldump --skip-extended-insert,它会创建可以通过git更好地跟踪/扩散的转储。

还有一些关于最佳存储库配置的提示,以减少磁盘大小。复制自here

  • core.compression = 9 :标记gzip以指定blob和包的压缩级别。级别1的文件大小越大,级别9越长,但压缩效果越好。
  • repack.usedeltabaseoffset = true :出于兼容性原因,默认为false,但Git> = 1.4.4支持。
  • pack.windowMemory = 100m :(重新)打包对象可能会占用大量内存。为了防止你的所有资源流失,对它施加一些限制是有用的。还有pack.deltaCacheSize。
  • pack.window = 15 :默认为10.使用更高的值,Git会更难找到类似的blob。
  • gc.auto = 1000 :默认为6700.如文章中所示,建议每隔一段时间运行一次git gc。我个人每天都运行git gc --auto,所以只有在有足够垃圾的情况下才能收拾东西。 git gc --auto通常只在周围有6700个松散物体时触发打包机制。此标志会降低此金额。
  • gc.autopacklimit = 10 :默认为50.每次运行git gc时,都会生成一个松散对象的新包。随着时间的推移,你会得到太多的包,浪费空间。将所有包装偶尔组合成一个包装是个好主意,因此所有对象都可以组合和分层。默认情况下,当有50个包时,git gc会这样做。但对于这种情况,较低的数字可能会更好。

旧版本可以通过以下方式修剪:

git rebase --onto master~8 master~7

(从here复制)

答案 3 :(得分:1)

以下包括用于捕获mysql数据库/模式的git预提交钩子,给定user ='myuser',password ='mypassword',database_name ='dbase1'。适当地冒泡到git系统的错误(其他答案中的exit 0可能是危险的,可能无法正确处理错误情况)。 (可选)可以将数据库导入添加到post-checkout钩子(捕获所有数据时,而不仅仅是模式),但请注意数据库大小。下面的bash-script评论中的详细信息。

pre-commit hook:

#!/bin/bash

# exit upon error
set -e
# another way to set "exit upon error", for readability
set -o errexit

mysqldump -umyuser -pmypassword dbase1 --no-data=true > dbase1.sql

# Uncomment following line to dump all data with schema,
# useful when used in tandem for the post-checkout hook below.
# WARNING: can greatly expand your git repo when employing for
# large databases, so carefully evaluate before employing this method.
# mysqldump -umyuser -pmypassword dbase1 > dbase1.sql

git add dbase1.sql

(可选)结账后挂钩:

#!/bin/bash
# mysqldump (above) is presumably run without '--no-data=true' parameter.
set -e
mysql -umyuser -pmypassword dbase1 < dbase1.sql

应用程序的版本,我正在运行的操作系统:

root@node1 Dec 12 22:35:14 /var/www# mysql --version
mysql  Ver 14.14 Distrib 5.1.54, for debian-linux-gnu (x86_64) using readline 6.2
root@node1 Dec 12 22:35:19 /var/www# git --version
git version 1.7.4.1
root@node1 Dec 12 22:35:22 /var/www# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 11.04
Release:        11.04
Codename:       natty
root@node1 Dec 12 22:35:28 /var/www#

答案 4 :(得分:1)

听起来很棒(这个想法确实发生在我身上),当我试图实现它时,我碰到了一堵墙。理论上,通过使用--skip-extended-insert标志,尽管初始转储很大,但每日转储之间的差异应该是最小的,因此可以假设存储库随时间的大小增加也是最小的, ?错!

Git存储shapshots,而不是diffs,这意味着在每次提交时,它将占用整个转储文件,而不仅仅是diff。此外,由于带有--skip-extended-instert的转储将在每个插入行上使用所有字段名称,与没有--skip-extended-instert的转储相比,它将是巨大的。这导致尺寸爆炸,与人们预期的完全相反。

在我的情况下,使用~300MB的sql转储,存储库在几天内就达到了千兆字节。那么,我做了什么?我首先尝试了同样的事情,只删除--skip-extended-instert,这样转储会更小,快照也会按比例缩小。这种方法有一段时间了,但随着时间的推移它也变得无法使用。

尽管如此,使用--skip-extended-insert的diff使用实际上仍然是一个好主意,但现在我尝试使用subversion而不是git。我知道,与git相比,svn是古老的历史,但它看起来效果更好,因为它确实使用了差异而不是快照。

所以简而言之,我认为最好的解决方案是做上面的事情,但是使用subversion而不是git。

答案 5 :(得分:0)

虽然我没有使用Git,但我已经使用了源代码控制超过15年。在决定在源代码管理中存储src和附带资源的位置和方式时遵循的最佳实践:如果在项目中使用了DB Schema,那么您应该在“那个”项目中对模式和所有其他项目资源进行版本控制。如果您开发了一组在其他项目中重用的模式或编程资源,那么您应该为这些可重用资源创建一个单独的存储库。单独的可重用资源项目将自行进行版本化,并将跟踪该存储库中实际可重用资源的版本。

如果您在另一个项目中使用可重用资源库中的版本化资源,那么您将拥有以下场景(仅作为示例)。项目XYZ版本1.0现在使用DB Schema_ABC版本4.0在这种情况下,您将了解您已使用特定版本的可重用资源,并且由于它是版本化的,因此您将能够在整个项目中跟踪其使用情况。如果您收到有关DBSchema_ABC的错误报告,您将能够修复架构并重新版本以及了解DBSchem_ABC的使用位置以及您可能需要进行一些更改的位置。从那里您还将了解哪些项目包含哪些可重用资源的版本......您只需要了解如何跟踪您的资源。

采用这种类型的开发环境和资源管理策略是发布可用软件和管理中断/修复增强环境的关键。即使你是在自己的时间开发自己的edificcation,你应该使用源代码控制..因为你..

至于Git,如果可以的话,我会找到一个gui前端或dev env集成。 Git非常大,所以我相信它有很多前端支持,可能吗?

答案 6 :(得分:0)

(无耻插件)

dbvc commandline tool允许您管理存储库中的数据库架构更新。

它在数据库中创建并使用表_dbvc,其中包含运行的更新列表。您可以轻松运行尚未应用于数据库架构的更新。

该工具使用git来确定执行更新的正确顺序。

DBVC用法

显示命令列表

dbvc help

显示特定命令的帮助

dbvc help init

为现有数据库初始化DBVC。

dbvc init

创建数据库转储。这用于在新环境中创建数据库。

mysqldump foobar > dev/schema.php

使用架构创建数据库。

dbvc create

添加更新文件。这些用于更新其他环境中的数据库。

echo 'ALTER TABLE `foo` ADD COLUMN `status` BOOL DEFAULT 1;' > dev/updates/add-status-to-foo.sql

将更新标记为已运行。

dbvc mark add-status-to-foo

显示需要运行的更新列表。

dbvc status

显示所有状态更新。

dbvc status --all

更新数据库。

dbvc update

答案 7 :(得分:0)

我发现以下选项对于版本控制/ git兼容的mysqldump是必需的。

mysqldump --skip-opt --skip-comments |sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/'

(也许是--no-data

--skip-opt非常有用,它会夺走所有--add-drop-table --add-locks --create-options --disable-keys --extended-insert --lock-tables --quick --set-charset。当数据库包含触发器时,DEFINER sed是必需的。