将数据库更改从开发迁移到实时

时间:2008-08-29 19:02:34

标签: php mysql schema migration

推动新功能生存的最大风险可能在于新代码所需的数据库修改。在Rails中,我相信它们具有“迁移”,您可以在其中以编程方式对开发主机进行更改,然后在使用修订模式的代码中进行相同的更改。如果需要,可以同步方式滚动两个背面。

有没有人遇到过类似的PHP / MySQL工具集?很想听听它,或任何程序或流程解决方案,以帮助降低风险......

10 个答案:

答案 0 :(得分:5)

我从未遇到过能够胜任这项工作的工具。相反,我使用了单个文件,编号以便我知道运行它们的顺序:本质上是Rails迁移的手动版本,但没有回滚。

这就是我所说的那种事情:

000-clean.sql         # wipe out everything in the DB
001-schema.sql        # create the initial DB objects
002-fk.sql            # apply referential integrity (simple if kept separate)
003-reference-pop.sql # populate reference data
004-release-pop.sql   # populate release data
005-add-new-table.sql # modification
006-rename-table.sql  # another modification...

我从来没有遇到过这样做的任何问题,但它并不是很优雅。由您来跟踪需要为给定更新运行的脚本(更智能的编号方案可能有所帮助)。它也适用于源代码控制。

处理代理键值(来自自动编号列)可能很麻烦,因为生产数据库可能具有与开发DB不同的值。因此,如果可能的话,我尝试永远不要在任何修改脚本中引用文字代理键值。

答案 1 :(得分:5)

我不相信程序化迁移。如果这是一个简单的更改,例如添加NULLable列,我只需将其直接添加到实时服务器。如果它更复杂或需要更改数据,我将编写一对SQL迁移文件并针对副本数据库进行测试。

使用迁移时,始终测试回滚迁移。这是你的紧急“哦屎”按钮。

答案 2 :(得分:3)

之前我使用过此工具,效果很好。

http://www.mysqldiff.org/

它将数据库连接或SQL文件作为输入,并将其与相同(另一个数据库连接或另一个SQL文件)进行比较。它可以吐出SQL来进行更改或为您进行更改。

答案 3 :(得分:3)

@ [yukondude]

我自己正在使用Perl,并且我以同样的方式半手动地走了Rails式的迁移路线。

我所做的是有一个表“版本”,其中包含一列“版本”,其中包含一行数字,即当前架构版本。然后编写一个脚本来读取该编号,查看某个目录并应用所有编号的迁移从那里到达此处(然后更新数字)是非常简单的。

在我的dev / stage环境中,我经常(通过另一个脚本)将生产数据拉入临时数据库,然后运行迁移脚本。如果你在上线之前这样做,你将非常确定迁移是否有效。显然,您在临时环境中进行了广泛的测试。

我在一个版本控制标记下标记新代码和所需的迁移。要部署到暂存或直播,只需将所有内容更新到此标记并快速运行迁移脚本。 (如果真的是古怪的模式更改,您可能希望安排一个短暂的停机时间。)

答案 4 :(得分:3)

我使用的解决方案(最初由我的朋友开发)是yukondude的另一个附录。

  1. 在版本控制下创建一个模式目录,然后对每个数据库更改保留一个.sql文件,其中包含您要执行的SQL以及sql查询以更新db_schema表。
  2. 使用名为version。的整数列创建名为“db_schema”的数据库表。
  3. 在架构目录中创建两个shell脚本,“current”和“update”。执行current会告诉您当前所连接的数据库所使用的db模式版本。运行更新会按顺序执行编号大于db_schema表中版本的每个.sql文件,直到达到架构目录中编号最大的文件为止。
  4. 架构目录中的文件:

    0-init.sql 
    1-add-name-to-user.sql
    2-add-bio.sql
    

    典型文件的样子,请注意每个.sql文件末尾的db_schema更新:

    BEGIN;
    -- comment about what this is doing
    ALTER TABLE user ADD COLUMN bio text NULL;
    
    UPDATE db_schema SET version = 2;
    COMMIT;
    

    “当前”脚本(对于psql):

    #!/bin/sh
    
    VERSION=`psql -q -t <<EOF
    \set ON_ERROR_STOP on
    SELECT version FROM db_schema;
    EOF
    `
    
    [ $? -eq 0 ] && {
        echo $VERSION
        exit 0
    }
    
    echo 0
    

    更新脚本(也是psql):

    #!/bin/sh
    
    CURRENT=`./current`
    LATEST=`ls -vr *.sql |egrep -o "^[0-9]+" |head -n1`
    
    echo current is $CURRENT
    echo latest is $LATEST
    
    [[ $CURRENT -gt $LATEST ]] && {
        echo That seems to be a problem.
        exit 1
    }
    
    [[ $CURRENT -eq $LATEST ]] && exit 0
    
    #SCRIPT_SET="-q"
    SCRIPT_SET=""
    
    for (( I = $CURRENT + 1 ; I <= $LATEST ; I++ )); do
        SCRIPT=`ls $I-*.sql |head -n1`
        echo "Adding '$SCRIPT'"
        SCRIPT_SET="$SCRIPT_SET $SCRIPT"
    done
    
    echo "Applying updates..."
    echo $SCRIPT_SET
    for S in $SCRIPT_SET ; do
        psql -v ON_ERROR_STOP=TRUE -f $S || {
        echo FAIL
        exit 1
        }
    done
    echo OK
    

    我的0-init.sql具有完整的初始模式结构以及初始“UPDATE db_schema SET version = 0;”。不应该太难修改MySQL的这些脚本。在我的情况下,我也有

    export PGDATABASE="dbname"
    export PGUSER="mike"
    

    在我的.bashrc中。并且它会提示输入正在执行的每个文件的密码。

答案 5 :(得分:2)

Symfony有一个名为sfMigrationsLight的插件,用于处理基本迁移。 CakePHP也有迁移。

无论出于何种原因,迁移支持从未真正成为大多数PHP框架和ORM的高优先级。

答案 6 :(得分:2)

我使用SQLyog来复制结构,我总是让我重复总是先备份。

答案 7 :(得分:2)

几乎是Lot105所描述的。

每次迁移都需要一个apply和rollback脚本,并且您有某种控制脚本可以检查需要应用哪些迁移并以适当的顺序应用它们。

然后,每个开发人员使用此方案使其数据库保持同步,并且在应用于生产时,将应用相关更改。如果有必要,可以保留回滚脚本以撤消更改。

使用简单的ALTER脚本无法完成某些更改,例如sqldiff会生成的工具;某些更改不需要架构更改,但需要对现有数据进行编程更改。所以你无法真正概括,这就是为什么你需要一个人工编辑的脚本。

答案 8 :(得分:0)

我一直希望让我的开发网站指向与实际网站相同的数据库。这听起来有点冒险,但实际上它解决了许多问题。如果同一服务器上有两个站点指向同一个数据库,则可以实时准确地查看用户在其上线时将看到的内容。

您将只拥有1个数据库,只要您将策略永远不从表中删除列,您就知道您的新代码将与您正在使用的数据库匹配。

迁移时的破坏程度也大大降低。您只需要移动PHP脚本,并且已经使用相同的数据库进行了测试。

我还倾向于为任何用户上传目标的文件夹创建符号链接。这意味着不会混淆哪些用户文件已更新。

另一个副作用是选择移植一小组“beta-testers”以在日常使用中使用该网站。这可以带来很多反馈,您可以在公开发布之前实现

这可能不适用于所有情况,但我已开始将所有更新移至此模型。它使得开发和发布更顺畅。

答案 9 :(得分:0)

过去我使用了LiquiBase,这是一个基于Java的工具,您可以将迁移配置为XML文件。您可以使用它生成必要的SQL。

今天我使用Doctrine 2库,其中migration facilities类似于Ruby。

Symfony 2框架也有一种处理架构更改的好方法 - 它的命令行工具可以分析现有架构并生成SQL以使数据库与更改的架构定义相匹配。