DB:模式:负载与DB:与Capistrano迁移[英] db:schema:load vs db:migrate with capistrano

本文是小编为大家收集整理的关于DB:模式:负载与DB:与Capistrano迁移的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个正在移至另一台服务器的Rails应用程序,我认为我应该使用DB:架构:加载来创建MySQL数据库,因为建议使用它.我的问题是我正在使用Capistrano进行部署,并且似乎默认为Rake DB:迁移.有没有办法更改此问题,或者是使用DB的Capistrano是有充分理由迁移的?

推荐答案

为什么要使用db:架构:load

我发现我自己的迁移最终会进行一些数据改组(假设我将first_name和last_name列组合到一个full_name列中).一旦我这样做,我就开始使用ActivereCord通过数据库记录进行筛选,您的模型最终对某些列进行了假设.例如,我的"人"表稍后得到了一个"位置"列,然后将人们分类.现在,较早的迁移无法选择数据,因为"位置"列还不存在.

如何更改Capistrano中的默认行为

总而言之,我相信deploy:cold 应该使用db:schema:load而不是db:migrate.我通过更改Capistrano在冷部部署中执行的中间步骤解决了这个问题.对于Capistrano v2.5.9,库代码中的默认任务如下.

namespace :deploy do
  ...
  task :cold do
    update
    migrate  # This step performs `rake db:migrate`.
    start
  end
  ...
end

i在我的deploy.rb中覆盖了任务.

namespace :deploy do
  task :cold do       # Overriding the default deploy:cold
    update
    load_schema       # My own step, replacing migrations.
    start
  end

  task :load_schema, :roles => :app do
    run "cd #{current_path}; rake db:schema:load"
  end
end

其他推荐答案

在安德烈斯·贾恩·塔克斯(Andres Jaan Tack),亚当·斯皮尔斯(Adam Spiers)和卡米尔·瓦尼鲁伊(Kamiel Wanrooij)的肩膀上爬上来,我已经建立了以下任务以覆盖部署:冷.

task :cold do
  transaction do
    update
    setup_db  #replacing migrate in original
    start
  end
end

task :setup_db, :roles => :app do
  raise RuntimeError.new('db:setup aborted!') unless Capistrano::CLI.ui.ask("About to `rake db:setup`. Are you sure to wipe the entire database (anything other than 'yes' aborts):") == 'yes'
  run "cd #{current_path}; bundle exec rake db:setup RAILS_ENV=#{rails_env}"
end

我的增强功能是...

  • 将其包裹在transaction do中,以便Capistrano在中止后会进行适当的回滚.
  • 做db:setup而不是db:schema:load,因此,如果数据库不存在,则将在加载架构之前创建它.

其他推荐答案

这是安德烈斯·贾恩·塔克斯(Andres Jaan Tack)的好答案.我只是想添加一些评论.

首先,这是Andres'deploy:load_schema任务的改进版本,其中包括警告,更重要的是使用bundle exec和RAILS_ENV来确保正确设置环境:

namespace :deploy do
  desc 'Load DB schema - CAUTION: rewrites database!'
  task :load_schema, :roles => :app do
    run "cd #{current_path}; bundle exec rake db:schema:load RAILS_ENV=#{rails_env}"
  end
end

我已经提交了在Capistrano中实现的功能请求.在该要求中,我注意到'db:schema:load vs. vs. '辩论已经在Capistrano讨论小组,并且有些不愿将deploy:cold任务切换到db:migrate上的db:schema:load,因为如果无意间运行,前者是整个数据库,而后者可能会抱怨和保释无害.尽管如此,从技术上讲,db:schema:load是更好的方法,因此,如果可以减轻意外数据丢失的风险,那么值得切换.

本文地址:https://www.itbaoku.cn/post/597487.html

问题描述

I have a rails app that I'm moving to another server and I figure I should use db:schema:load to create the mysql database because it's recommended. My problem is that I'm using capistrano to deploy and it seems to be defaulting to rake db:migrate instead. Is there a way to change this or is capistrano using db:migrate for a good reason?

推荐答案

Why to use db:schema:load

I find that my own migrations eventually do some shuffling of data (suppose I combine first_name and last_name columns into a full_name column, for instance). As soon as I do any of this, I start using ActiveRecord to sift through database records, and your models eventually make assumptions about certain columns. My "Person" table, for instance, was later given a "position" column by which people are sorted. Earlier migrations now fail to select data, because the "position" column doesn't exist yet.

How to change the default behavior in Capistrano

In conclusion, I believe deploy:cold should use db:schema:load instead of db:migrate. I solved this problem by changing the middle step which Capistrano performs on a cold deploy. For Capistrano v2.5.9, the default task in the library code looks like this.

namespace :deploy do
  ...
  task :cold do
    update
    migrate  # This step performs `rake db:migrate`.
    start
  end
  ...
end

I overrode the task in my deploy.rb as follows.

namespace :deploy do
  task :cold do       # Overriding the default deploy:cold
    update
    load_schema       # My own step, replacing migrations.
    start
  end

  task :load_schema, :roles => :app do
    run "cd #{current_path}; rake db:schema:load"
  end
end

其他推荐答案

Climbing up on the shoulders of Andres Jaan Tack, Adam Spiers, and Kamiel Wanrooij, I've built the following task to overwrite deploy:cold.

task :cold do
  transaction do
    update
    setup_db  #replacing migrate in original
    start
  end
end

task :setup_db, :roles => :app do
  raise RuntimeError.new('db:setup aborted!') unless Capistrano::CLI.ui.ask("About to `rake db:setup`. Are you sure to wipe the entire database (anything other than 'yes' aborts):") == 'yes'
  run "cd #{current_path}; bundle exec rake db:setup RAILS_ENV=#{rails_env}"
end

My enhancements here are...

  • wrap it in transaction do, so that Capistrano will do a proper rollback after aborting.
  • doing db:setup instead of db:schema:load, so that if the database doesn't already exist, it will be created before loading the schema.

其他推荐答案

That's a great answer from Andres Jaan Tack. I just wanted to add a few comments.

Firstly, here's an improved version of Andres' deploy:load_schema task which includes a warning, and more importantly uses bundle exec and RAILS_ENV to ensure that the environment is set up correctly:

namespace :deploy do
  desc 'Load DB schema - CAUTION: rewrites database!'
  task :load_schema, :roles => :app do
    run "cd #{current_path}; bundle exec rake db:schema:load RAILS_ENV=#{rails_env}"
  end
end

I have submitted a feature request to have deploy:load_schema implemented in Capistrano. In that request, I noted that the 'db:schema:load vs. db:migrate' debate has already been covered in the Capistrano discussion group, and there was some reluctance to switch the deploy:cold task to using db:schema:load over db:migrate, since if run unintentionally, the former nukes the entire database whereas the latter would probably complain and bail harmlessly. Nevertheless db:schema:load is technically the better approach, so if the risk of accidental data loss could be mitigated, it would be worth switching.