[mysql] 실패한 Rails 마이그레이션 롤백

실패한 Rails 마이그레이션을 어떻게 롤백합니까? rake db:rollback실패한 마이그레이션을 취소 할 것으로 예상 하지만 이전 마이그레이션 (실패한 마이그레이션에서 1을 뺀 마이그레이션)을 롤백합니다. 그리고 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 : 마이그레이션 ============================================ ========
-add_column (: assets, : test, : integer)
   -> 0.0932 초
-add_column (: asset, : error)
레이크 중단!
오류가 발생하여 이후의 모든 마이그레이션이 취소되었습니다.

잘못된 인수 개수 (3 개에 2 개)

좋아, 롤백하자.

$ rake db : rollback
== AddLevelsToRoles : 되돌리기 ============================================ ==
-remove_column (: roles, : level)
   -> 0.0778 초
== AddLevelsToRoles : 되돌림 (0.0779s) =====================================

응? 그것은 실패한 마이그레이션이 아니라 SimpleTest 이전의 마지막 마이그레이션이었습니다. (오, 마이그레이션 출력에 버전 번호가 포함되어 있으면 좋을 것입니다.)

따라서 실패한 마이그레이션 SimpleTest에 대해 아래로 실행 해 보겠습니다.

$ rake db : migrate : down VERSION = 20090326173033
$

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

$ rake db : migrate : up VERSION = 20090326173033
== SimpleTest : 마이그레이션 ============================================ ========
-add_column (: assets, : test, : integer)
레이크 중단!
Mysql :: Error : 중복 열 이름 'test': ALTER TABLE`assets` ADD`test` int (11)

아니. 분명히 migrate : down이 작동하지 않았습니다. 실패하지 않고 실행되지 않습니다.

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



답변

불행히도 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. 상향 마이그레이션의 어느 부분이 효과가 있는지 파악하십시오. 주석 처리하십시오.
  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에서 실패한 마이그레이션은 2009 년과 마찬가지로 Rails가 제공하는 표준 레이크 작업으로 수정할 수 없습니다.

MySql은 DDL 구문의 롤백을 지원하지 않습니다 ( MySQL 5.7 Manual에서 ). 그리고 Rails는 그것으로 아무것도 할 수 없습니다.

또한 Rails가 작업을 수행하는 방법을 확인할 수 있습니다 . 연결 어댑터가 .NET에 응답하는 방식에 따라 마이그레이션이 트랜잭션으로 래핑 됩니다 :supports_ddl_transactions?. Rails 소스 (v 4.2.1)에서이 작업을 검색 한 후 Sqlite3PostgreSql 만 트랜잭션을 지원하며 기본적으로 지원되지 않음을 발견했습니다.

편집
따라서 원래 질문에 대한 현재 답변 : 실패한 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 (페이스 티로 클릭)