管理数据库更改

时间:2012-03-29 19:20:13

标签: postgresql deployment migration schema rails-migrations

我开始使用触发器,视图,函数,CTE等将更多逻辑移入数据库。当plv8 / json出现在postgres中时,我可以看到自己在那里放了很多逻辑。

我遇到了在续集和activerecord中进行数据库迁移的“标准”方法的问题。续集和activerecord都允许您将任意sql代码放入带时间戳的文件中。运行每个文件时,将使用文件名(或文件名中的时间戳)更新schema_versions表,该表记录了已将哪些迁移应用于当前数据库。

如果在数据库级别进行大量编码,则意味着对现有视图,函数等的修改遵循以下模式:

迁移1 定义了一个函数和一个使用该函数的视图。

-- Migration 1
create function calculate(x int) returns int as $$                              
  return x + 1;                                                                 
$$ language sql;                                                                

create view foos as (                                                           
  select something, calculate(something) from a_table                           
);  

需求发生变化,我需要更改功能类型。在 Migration 2 中,我必须删除依赖于foo的所有对象,并通过复制它们的整个身体来重新创建它们 - 即使大多数其他代码没有任何更改!

-- Migration 2                                                              

-- Have to drop all views and functions that depend on the                  
-- `calculate(int)` function.                                               
drop view foos;                                                             
create or replace calculate(x bigint) returns bigint as $$                  
  return x + 1;                                                             
$$ language sql;                                                            

-- I could do `drop function calculate(int) cascade`,                       
-- but I might accidentally drop some objects that wouldn't get recreated below.

-- Now I have to recreate foo.                                              
create view foos as (                                                       
  select something, calculate(something) from a_table                       
);

如果我正在构建基于视图,函数和触发器的系统,那么我的迁移将填充重复的代码,并且很难找到最新版本的代码。您可能会说“不要那样做!”,但就我的目的而言(电子商务,运输,交易),我发现让数据库通过逻辑确保数据的完整性更容易,更快捷在数据库内。

您当然可以转储当前的数据库架构(包括所有代码定义),但我认为您会丢失注释。而且您通常不希望编辑包含整个架构的巨型文件。

有关如何解决此问题的任何想法?

我最好的想法是如何将sql代码包含在自己的规范文件中(app / sql / orders / shipping.sql,app / sql / orders / creation.sql等)。每个人都直接在这些上发展。无论什么时候发布,你都需要创建一个新的迁移文件,查看自上一版本以来所有已更改的代码,找出需要删除和重新创建的数据库对象的依赖关系链,然后复制将sql从规范的sql文件转换为新的续集/ activerecord迁移文件。但这很痛苦。 :/

非常欢迎思考。我希望我能够很好地解释这一点,我正在削减我的咖啡因摄入量,而且我有点昏昏欲睡。

哦,我在Stack Overflow上问了一个类似的问题:Changing the type of a column used in other views答案是让我传入的功能:

  • 运行的SQL代码
  • 要删除并重新创建的数据库视图

该函数将检索视图定义,删除视图,运行sql代码,然后重新创建视图定义(以丢弃的相反顺序)。也许像这样的函数系统可以帮助解决必须将sql代码复制/粘贴到迁移文件中的问题。

2 个答案:

答案 0 :(得分:4)

我建议liquibase

您创建跟踪数据库更改的文件,这些文件将以正确的迁移顺序运行到数据库中。

答案 1 :(得分:1)

你可能会发现Dave Wheeler的博客帖子从这里开始很有趣:

http://justatheory.com/computers/databases/simple-sql-change-management.html

我的数据库更改速度相当小,但我倾向于粗心大意并直接对架构进行小的更改,因此我必须提出一些基础设施,以便在我完成时抓住。基本要素是:

  1. 可以从头开始重建开发数据库的makefile
  2. 一组模式文件,分为“modules”(lookups_schema.sql,lookup_data.sql)
  3. 一组从一个修订版过渡到下一个修订版的更新文件
  4. 我通常没有相应的降级脚本,有些人会这样做
  5. 使用合理数量的测试数据填充数据库的脚本
  6. 最重要的是,通过pgTAP的测试套件可以检查我的各种功能,视图以及升级脚本。升级测试也可以针对实时数据库运行。
  7. 如果你有一个单独的PostgreSQL实例设置,关闭/打开ramdisk等fsync,那么重建整个数据库并填充它可能需要几秒钟(如果你没有太多的测试数据)。

    从#1,#2开始,然后添加#6(pgTAP 非常酷),其余的。关键是测试套件可以检查您的数据库内代码。

    有些工具会尝试为您自动化架构更改,但它们实际上只擅长向表中添加新列等等。一旦你的数据库中有代码,那么它们就没什么用了。