我觉得我的商店有一个漏洞,因为我们没有一个可靠的过程来控制数据库模式更改的版本。我们做了很多备份,所以我们或多或少地得到了保护,但以这种方式依赖于最后一道防线是一种糟糕的做法。
令人惊讶的是,这似乎是一个共同的主线。与我交谈过的许多商店都忽略了这个问题,因为他们的数据库不会经常更改,他们基本上只是尽量做到一丝不苟。
不过,我知道这个故事是怎么发展的。这只是时间问题,迟早会出问题,会有东西丢失。
在这方面有什么最佳实践吗?你有哪些行之有效的策略?
我觉得我的商店有一个漏洞,因为我们没有一个可靠的过程来控制数据库模式更改的版本。我们做了很多备份,所以我们或多或少地得到了保护,但以这种方式依赖于最后一道防线是一种糟糕的做法。
令人惊讶的是,这似乎是一个共同的主线。与我交谈过的许多商店都忽略了这个问题,因为他们的数据库不会经常更改,他们基本上只是尽量做到一丝不苟。
不过,我知道这个故事是怎么发展的。这只是时间问题,迟早会出问题,会有东西丢失。
在这方面有什么最佳实践吗?你有哪些行之有效的策略?
当前回答
是的,当然。每当有更改时,我们生成PostgreSQL模式的转储并签入。它已经救了我们很多次,而我才上任几个月。
其他回答
数据库本身?没有
创建它们的脚本,包括静态数据插入、存储过程等;当然可以。它们是文本文件,它们包含在项目中,像其他东西一样签入和签出。
当然,在理想情况下,您的数据库管理工具可以做到这一点;但你必须遵守纪律。
我们维护由ER工具(PowerAMC)生成的DDL(有时是DML)脚本。
我们有一个shell脚本工作台,它重命名以主干分支上的数字开头的脚本。 提交每个脚本并标记bugzilla编号。
这些脚本在需要时与应用程序代码合并到发布分支中。
我们有一个记录脚本及其状态的表。 在部署工具的每次安装中,每个脚本都按顺序执行,并记录在此表中。
“简短版本:将您的生产数据库转储到git存储库中,以实现即时备份解决方案。”
The most successful scheme I've ever used on a project has combined backups and differential SQL files. Basically we would take a backup of our db after every release and do an SQL dump so that we could create a blank schema from scratch if we needed to as well. Then anytime you needed to make a change to the DB you would add an alter scrip to the sql directory under version control. We would always prefix a sequence number or date to the file name so the first change would be something like 01_add_created_on_column.sql, and the next script would be 02_added_customers_index. Our CI machine would check for these and run them sequentially on a fresh copy of the db that had been restored from the backup.
我们还准备了一些脚本,开发人员可以用一个命令将本地db重新初始化到当前版本。
You should never just log in and start entering "ALTER TABLE" commands to change a production database. The project I'm on has database on every customer site, and so every change to the database is made in two places, a dump file that is used to create a new database on a new customer site, and an update file that is run on every update which checks your current database version number against the highest number in the file, and updates your database in place. So for instance, the last couple of updates:
if [ $VERSION \< '8.0.108' ] ; then
psql -U cosuser $dbName << EOF8.0.108
BEGIN TRANSACTION;
--
-- Remove foreign key that shouldn't have been there.
-- PCR:35665
--
ALTER TABLE migratorjobitems
DROP CONSTRAINT migratorjobitems_destcmaid_fkey;
--
-- Increment the version
UPDATE sys_info
SET value = '8.0.108'
WHERE key = 'DB VERSION';
END TRANSACTION;
EOF8.0.108
fi
if [ $VERSION \< '8.0.109' ] ; then
psql -U cosuser $dbName << EOF8.0.109
BEGIN TRANSACTION;
--
-- I missed a couple of cases when I changed the legacy playlist
-- from reporting showplaylistidnum to playlistidnum
--
ALTER TABLE featureidrequestkdcs
DROP CONSTRAINT featureidrequestkdcs_cosfeatureid_fkey;
ALTER TABLE featureidrequestkdcs
ADD CONSTRAINT featureidrequestkdcs_cosfeatureid_fkey
FOREIGN KEY (cosfeatureid)
REFERENCES playlist(playlistidnum)
ON DELETE CASCADE;
--
ALTER TABLE ticket_system_ids
DROP CONSTRAINT ticket_system_ids_showplaylistidnum_fkey;
ALTER TABLE ticket_system_ids
RENAME showplaylistidnum
TO playlistidnum;
ALTER TABLE ticket_system_ids
ADD CONSTRAINT ticket_system_ids_playlistidnum_fkey
FOREIGN KEY (playlistidnum)
REFERENCES playlist(playlistidnum)
ON DELETE CASCADE;
--
-- Increment the version
UPDATE sys_info
SET value = '8.0.109'
WHERE key = 'DB VERSION';
END TRANSACTION;
EOF8.0.109
fi
我相信有更好的方法来做到这一点,但到目前为止,它对我来说是有效的。