문제

실패한 레일 마이그레이션을 어떻게 롤백합니까? 나는 그것을 기대할 것이다 rake db:rollback 마이그레이션 실패를 취소하지만, 이전 마이그레이션을 롤백합니다 (실패 마이그레이션 마이너스). 그리고 rake db:migrate:down VERSION=myfailedmigration 작동하지 않습니다. 나는 이것에 몇 번 만났고 그것은 매우 실망 스럽다. 다음은 문제를 복제하기 위해 간단한 테스트입니다.

class SimpleTest < ActiveRecord::Migration
  def self.up
    add_column :assets, :test, :integer
    # the following syntax error will cause the migration to fail
    add_column :asset, :test2, :integer
  end

  def self.down
    remove_column :assets, :test
    remove_column :assets, :test2
  end
end

결과:

==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
   -> 0.0932s
-- add_column(:asset, :error)
rake aborted!
An error has occurred, all later migrations canceled:

wrong number of arguments (2 for 3)

좋아, 다시 롤백하자 :

$ rake db:rollback
==  AddLevelsToRoles: reverting ===============================================
-- remove_column(:roles, :level)
   -> 0.0778s
==  AddLevelsToRoles: reverted (0.0779s) ======================================

뭐? 그것은 실패한 마이그레이션이 아니라 단순하기 전의 마지막 마이그레이션이었습니다. (그리고 마이그레이션 출력에 버전 번호가 포함되어 있으면 좋을 것입니다.)

따라서 실패한 마이그레이션을 단순화하기 위해 아래로 실행해 보겠습니다.

$ rake db:migrate:down VERSION=20090326173033
$

아무 일도 일어나지 않으며 출력도 없습니다. 하지만 어쨌든 마이그레이션을 실행했을까요? 따라서 단순한 마이그레이션에서 구문 오류를 수정하고 다시 실행하십시오.

$ rake db:migrate:up VERSION=20090326173033
==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
rake aborted!
Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)

아니요. 분명히 마이그레이션 : 다운은 작동하지 않았습니다. 실패하지 않고 단지 실행되지 않습니다.

데이터베이스에 수동으로 들어가서 제거 한 다음 테스트를 실행하는 것 외에 해당 중복 테이블을 제거 할 방법이 없습니다. 그보다 더 나은 방법이 있어야합니다.

도움이 되었습니까?

해결책

불행히도 MySQL의 실패 마이그레이션을 수동으로 정리해야합니다. MySQL은 트랜잭션 데이터베이스 정의 변경을 지원하지 않습니다.

Rails 2.2에는 PostgreSQL의 트랜잭션 마이그레이션이 포함됩니다. Rails 2.3에는 SQLITE의 트랜잭션 마이그레이션이 포함됩니다.

이것은 현재 문제에 도움이되지 않지만 향후 프로젝트에 대한 데이터베이스를 선택할 수 있다면 거래 DDL을 지원하는 하나를 사용하는 것이 좋습니다.

업데이트 - Alejandro Babio에 의해 다른 답변에서보고 된 Rails 4.2.7 및 MySQL 5.7에서 2017 년에도 여전히 사실입니다.

다른 팁

지정된 버전으로 이동하려면 사용하십시오.

rake db:migrate VERSION=(the version you want to go to)

그러나 마이그레이션이 부분적으로 실패하면 먼저 정리해야합니다. 한 가지 방법은 다음과 같습니다.

  • 편집 down 의 일부를 취소하기위한 마이그레이션 방법 up 그것은 효과가있었습니다
  • 이전 상태로 다시 마이그레이션 (시작한 곳)
  • 마이그레이션 수정 (변경 사항을 취소 포함 down)
  • 다시 시도하십시오

좋아요, 여러분, 여기에 실제로 어떻게하는지 여기 있습니다. 위의 답변이 무슨 말을하는지 모르겠습니다.

  1. UP 마이그레이션의 어느 부분이 작동했는지 파악하십시오. 그것들을 언급하십시오.
  2. 또한 파산 한 마이그레이션의 일부를 언급/제거하십시오.
  3. 마이그레이션을 다시 실행하십시오. 이제 마이그레이션의 부러진 부분을 완성하여 이미 수행 된 부품을 건너 뜁니다.
  4. 결우 1 단계에서 언급 한 마이그레이션의 비트.

지금 당장 가지고 있는지 확인하려면 아래로 마이그레이션하고 백업 할 수 있습니다.

가능하면 PostgreSQL을 사용해야한다는 데 동의합니다. 그러나 MySQL에 집착하면 먼저 테스트 데이터베이스에서 마이그레이션을 시도하여 이러한 문제의 대부분을 피할 수 있습니다.

rake db:migrate RAILS_ENV=test

이전 상태로 되돌리고 다시 시도 할 수 있습니다.

rake db:schema:load RAILS_ENV=test

2015 년 Rails 4.2.1 및 MySQL 5.7로 Rails가 제공하는 표준 레이크 액션으로 마이그레이션이 실패 할 수 없습니다.

MySQL은 DDL Statments의 롤백을 지원하지 않습니다 ( MySQL 5.7 매뉴얼). 그리고 레일은 그것으로 아무것도 할 수 없습니다.

또한, 우리는 Rails가 어떻게 일을하는지 확인할 수 있습니다. 거래에 싸여 있습니다 연결 어댑터가 어떻게 응답하는지에 따라 :supports_ddl_transactions?. Rails Source (v 4.2.1) 에서이 조치를 검색 한 후 sqlite3 그리고 PostgreSQL 거래를 지원합니다 기본 지원되지 않습니다.

편집하다따라서 원래 질문에 대한 현재 답변 : 실패한 MySQL 마이그레이션은 수동으로 수정되어야합니다.

이를 수행하는 쉬운 방법은 거래에서 모든 행동을 마무리하는 것입니다.

class WhateverMigration < ActiveRecord::Migration

 def self.up
    ActiveRecord::Base.transaction do
...
    end
  end

  def self.down
    ActiveRecord::Base.transaction do
...
    end
  end

end

Luke Francl이 지적했듯이, "MySQL [Myisam 테이블은 트랜잭션을 지원하지 않는다"는데, 이는 일반적으로 MySQL을 피하거나 특히 Myisam을 피하는 것을 고려할 수 있습니다.

MySQL의 innodB를 사용하는 경우 위는 잘 작동합니다. 위 또는 아래의 오류가 다시 나옵니다.

알고 있어야합니다 거래를 통해 일부 유형의 조치를 취소 할 수 없습니다. 일반적으로 테이블 변경 (테이블을 떨어 뜨리거나 열 제거 또는 추가 등)을 롤백 할 수 없습니다.

콘솔에서 다운 마이그레이션 만 실행하십시오.

http://gilesbowkett.blogspot.com/2007/07/how-to-use-migrations-from-console.html (그의 Pastie로 클릭하십시오)

오타 ( "add_column"에서) : :

def self.up

add_column :medias, :title, :text
add_colunm :medias, :enctype, :text

def self.down

remove_column :medias, :title
remove_column :medias, :enctype   

그런 다음 문제 (일부 마이그레이션에 실패 할 수 없습니다). 인터넷 검색에 실패한 후 나는 이것을 달렸다 :

def self.up

remove_column :medias, :title
add_column :medias, :title, :text
add_column :medias, :enctype, :text

def self.down

remove_column :medias, :title
remove_column :medias, :enctype

보시다시피 수정 라인을 직접 추가 한 다음 확인하기 전에 다시 제거했습니다.

위의 Alejandro Babio의 답변은 최신 답변을 제공합니다.

추가하고 싶은 추가 세부 사항 :

myfailedmigration 마이그레이션이 실패하고 적용되는 것으로 간주되지 않으며 이는 실행을 통해 확인할 수 있습니다. rake db:migrate:status, 다음과 유사한 출력을 보여줍니다.

$  rake db:migrate:status
database: sample_app_dev

 Status   Migration ID    Migration Name
--------------------------------------------------
   up      20130206203115  Create users
   ...
   ...
   down    20150501173156  Test migration

의 잔류 효과 add_column :assets, :test, :integer 실패한 마이그레이션에서 실행되는 것은 데이터베이스 레벨에서 alter table assets drop column test; 질문.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top