免责声明:这是一个"最佳做法"问题,但我不确定如何用它来表达更具体或更客观的答案。
我有一个小型Rails项目的两个数据库:一个dev
数据库和一个prod
数据库,它们位于同一台服务器上。
每隔几周,我会通过一个dev Rails环境,通过ActiveAdmin gem对dev数据库进行一些数据更改(主要是插入)。我在Rails应用程序上查看,确保新数据看起来不错。当我准备好部署时,我运行一个脚本:
dev
db prod
db以删除所有数据dev
db转储导入prod
db 我的直觉告诉我,这不是解决这个问题的好方法,而且它也有点慢,但我似乎无法找到从一个数据库进行数据部署的标准方法到另一个。什么是标准方式,如果有的话?
我考虑过的事情:
一些补充说明:
答案 0 :(得分:2)
如果同一服务器上有两个数据库,则可以比较并插入表中。首先,对于已删除的行:
BEGIN TRAN;
DELETE FROM prod.tbl1
WHERE id IN (
SELECT id FROM dev.tbl1 RIGHT JOIN prod.tbl1 ON dev.tbl1.id = prod.tbl1.id WHERE dev.tbl1.id IS NULL);
COMMIT;
其次,对于新行:
BEGIN TRAN;
INSERT INTO prod.tbl1
SELECT *
FROM dev.tbl1
WHERE id IN (
SELECT id FROM dev.tbl1 LEFT JOIN prod.tbl1 ON dev.tbl1.id = prod.tbl1.id WHERE prod.tbl1.id IS NULL);
COMMIT;
现在,您的dev数据库上的触发器用于管理更新:
CREATE DEFINER=`root`@`localhost` TRIGGER `dev`.`tbl1_update`
AFTER UPDATE ON `dev`.`tbl1`
FOR EACH ROW
BEGIN
SET NEW.update = '1';
END
您需要更新"开发表上的字段。当在表上运行更新查询时,字段"更新"自动更改为1。然后,使用此查询:
BEGIN TRAN;
UPDATE prod.tbl1
LEFT JOIN dev.tbl1
ON prod.tbl1.id = dev.tbl1.id
SET prod.tbl1.fld1 = dev.tbl1.fld1, prod.tbl1.fld2 = dev.tbl1.fld2
WHERE prod.tbl1.id IN (SELECT id FROM dev.tbl1 WHERE update = '1');
UPDATE dev.tbl1 SET update = '0';
COMMIT;
您可以在所有表格上运行这样的查询。您可以将它放在.sql文件中并使用cron作业运行(mysql -h -u -D< myscript.sql)。
此查询比较表并获取生产中不存在的dev上的ID。然后,对整个表执行select(仅这些id),并将它们插入prod。
(用每个表的唯一标识符替换id字段)。
答案 1 :(得分:2)
这似乎是一种非常奇怪的方法。通常development
中的数据被视为一次性数据。您只需要足够的数据,以便进行样式设置和故障排除 - 通常使用伪随机数据。建立"完成"开发中的应用程序数据似乎容易出错,如果您是多个开发人员,则需要同步工作。
另外,如果数据集非常大,由于缺少缓存,Rails的开发速度会很慢。
您想要的是一个临时环境,它在与预期生产相同的设置下运行。这里的关键是它应该尽可能接近生产。这可以在远程服务器或Intranet中的服务器上运行。
您还可以使用暂存环境向客户/利益相关者显示新功能或进度,让他们预览新功能或循环开发进度。
您可以通过复制config/environments/production.rb -> staging.rb
并在预期的登台服务器上将RAILS_ENV
env var设置为staging
来创建它。
您还应该在config/database.yml
中创建其他部分或使用ENV['DATABASE_URL']
。
根据项目,可以使用生产中的镜像数据每天刷新暂存,也可以完全同步。