我们在Postgres中有一个架构,我们想要建立一个很好的方法来应用架构补丁。
目前,我们有一系列DDL文件可以创建模式,表格,序列,函数等。我们还有一个用于测试环境的填充脚本。这些文件都用于重新创建我们的数据库环境,用于开发,测试等。
我们还有许多与我们系统版本相对应的“补丁”文件。即。 patches / 1.0.0.sql,patches / 1.0.1.sql等。这些文件用于更新我们的登台和生产数据库。
到目前为止,这个过程对我们有用,但内部有一些争论如何最好地修补架构。
我很好奇其他人有什么,作为一个过程,修补登台和生产模式以及如何管理数据库的版本。
谢谢!
答案 0 :(得分:3)
在工作中,对于SQL Server,我们编写模式更改脚本,首先回滚要进行的更改(同样,即使尚未应用模式更改,回滚部分也能正常运行),然后是应用更改。在TSQL中,可以很容易地查看系统目录或其他表,以查看表/列/索引/行是否已存在,如果不存在则不执行任何操作。
在PostgreSQL中,您可以更简单地使用可以发送到服务器的命令来约束 - 但另一方面,DDL是事务性的,因此不应该发生半应用的模式更改。我已经适应了我以前在工作中使用的方案,以便在我自己的小项目中使用得很好(过度杀伤?但即使在这里我也有一个dev / test db和一个“真正的”db),例如:
\echo Rolling back schema change #35
BEGIN;
DELETE FROM schema_version WHERE schema_id = 35;
DROP TABLE IF EXISTS location_coordinates;
DROP FUNCTION IF EXISTS location_coordinates_populate();
END;
\echo Applying schema change #35
BEGIN;
INSERT INTO schema_version(schema_id, description) VALUES(35, 'Add location_coordinates table');
CREATE TABLE location_coordinates(
location_id INT PRIMARY KEY REFERENCES location(location_id),
latitude FLOAT NOT NULL,
longitude FLOAT NOT NULL,
earth_coordinates earth NOT NULL,
box_10miles cube NOT NULL
);
GRANT SELECT, INSERT, UPDATE, DELETE ON location_coordinates TO ui;
CREATE FUNCTION location_coordinates_populate() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$
BEGIN
new.earth_coordinates := ll_to_earth(new.latitude, new.longitude);
new.box_10miles := earth_box(new.earth_coordinates, 10 * 1609.344);
RETURN new;
END
$$;
CREATE TRIGGER location_coordinates_populate BEFORE INSERT OR UPDATE ON location_coordinates
FOR EACH ROW EXECUTE PROCEDURE location_coordinates_populate();
INSERT INTO location_coordinates(location_id, latitude, longitude)
SELECT location_id, latitude, longitude FROM location WHERE latitude IS NOT NULL AND longitude IS NOT NULL;
CREATE INDEX location_coordinates_10miles ON location_coordinates USING gist (box_10miles);
END;
\echo Done
只需使用“psql -f schema-changes / 35.sql”就可以在数据库上运行此脚本。通过切断“应用...”消息,我可以获得将其回滚的命令。正如您所看到的,更改维护了元数据表“schema_version”,因此我可以看到应用了哪些更改。整个更改是作为事务,数据迁移和所有操作完成的。在这里,我使用了DROP命令的“IF EXISTS”功能,即使在未应用更改时也使回滚部分感到满意。 Istr我们为Oracle工作的一件事是将模式更改写为PL / SQL--您可能在plpgsql中有一些函数来帮助进行更改吗?
请注意,在上面的更改中,我将“纬度”和“经度”列(可以为空)从“位置”迁移到单独的“location_coordinates”关系(并添加了earthdistance内容),我没有删掉旧的列。我们必须要注意的一件事是,如果可能的话,使模式更改向后兼容。因此,我可以在更新应用程序之前应用此架构更改以使用新表。在更新应用后,我会进行第二次更改以删除旧列以应用。在工作中,这些将在两个不同的发布周期中完成,因此在发布X期间,我们仍然可以选择回滚应用程序以释放X-1,而不必首先回滚所有模式更改;以及能够在应用程序之前在单独的窗口中部署架构更改。 (从技术上讲,我应该写一个触发器,因此对旧表的更新会同步到新表,但我没有,因为这太像工作了:))
我们还有一些应用程序可以抓住我们所有的数据库来查看schema_version
表中的内容,并跟踪更改,这样人们甚至可以看到在不必连接的情况下进行了哪些更改,并了解了每个变化的历史(我们跟踪“在开发中回滚”,“在开发中应用”等)。在工作中,我们的schema_version表还包括作者信息等。从版本控制应用版本信息的一种神奇方式很酷 - 我们遇到的一个问题是,如果SC在QA中应用,例如,然后在Perforce中更改,可能没有 - 一个通知。因此,应用跟踪架构更改35版本#4的方法会很好。
有一点需要注意 - 我们的架构更改的编号与应用程序版本无关。显然它们是相关的 - 这是蜘蛛应用程序允许人们进入的另一件事 - 但我们尝试进行许多小改动,而不是一个巨大的“这里是发布X的所有内容”补丁。模式更改也用于添加新索引等内容,因此可能根本不是应用程序驱动的。通常,架构更改由开发人员“拥有”,而不是DBA-尽管在上面的“创建索引”示例中,DBA基本上扮演开发人员角色并拥有架构更改。是的,我们坚持从开发人员那里获得高水平的SQL能力 - 尽管公司中的其他团队的工作方式略有不同,并且为数据库团队提供了更多的工作。