중간 migration을 한 번 더 실행시키는 방법
환경
Amazon Linux
# rake about
sinatra 1.4.7
ruby 2.3.1p112
Environment staging
Database adapter mysql2
Database schema version 201610xxxxxxxxx
배경
스테이징 환경은 여러 멤버가 만나고 있습니다. 어느새, migration는 이렇게 느꼈다.
# RACK_ENV=staging bundle exec rake db:migrate:status
database: xxx_staging
Status Migration ID Migration Name
--------------------------------------------------
up 20160826080803 Create xxx
up 20160929044948 Create xxx
up 20160929045000 Create xxx
up 20160929045041 Create xxx
up 20161111073930 A(add column is_prime)
up 20161116033102 B
up 20161116105100 C
확실히 전부 migration 전부 실행되고 있는 것처럼 보입니다만, 확인해 보면, [A]는 실행되고 있지 않는 것 같습니다. 다음 오류가 발생했습니다.
ActiveModel::UnknownAttributeError - unknown attribute 'is_prime' for table_a
즉시 db/structure.sql 파일을 확인한 후 table_a에 is_prime이 없었습니다. 즉, 중간 migration(A)가 실행되지 않음
대책
다시 시도
물론 DB를 지우고 모든 migration을 다시 시작하는 것은 가장 빠르지만 데이터를 내보내고 가져오지 않으면 안 되고 조금 번거롭고 나중에 발생할 가능성이 낮습니다만, 만약 프로덕션 그런 일이 일어나면 어떻게 대응해야할까.
mysqldump -uroot db_name > dump.sql
RACK_ENV=staging bundle exec rake db:drop && RACK_ENV=staging bundle exec rake db:create && RACK_ENV=staging bundle exec rake db:migrate
mysql -uroot db_name < dump.sql
다른 방법
그 migration만 실행시켜 보았다
RACK_ENV=staging bundle exec rake db:migrate:redo VERSION=20161111073930
그러면 다음 오류가 발생했습니다.
Mysql2::Error: Can't drop 'is_prime'; check that column/key exist:
즉, redo는 [down & up]이라는 구현이 되어 있습니다.
롤백했다.
RACK_ENV=staging bundle exec rake db:rollback STEP=4
↑와 같은 에러가 나왔다.
Mysql2::Error: Can't drop 'is_prime'; check that column/key exist:
한 걸음씩 하면 [A]까지는 할 수 있어 이런 느낌이 듭니다.
# RACK_ENV=staging bundle exec rake db:migrate:status
database: xxx_staging
Status Migration ID Migration Name
--------------------------------------------------
up 20160826080803 Create xxx
up 20160929044948 Create xxx
up 20160929045000 Create xxx
up 20160929045041 Create xxx
up 20161111073930 A(add column is_prime)
down 20161116033102 B
down 20161116105100 C
글쎄, 맞아! 원래 지금 is_prime는 존재하지 않기 때문입니다.
migration 파일을 제거해 보았습니다.
migration은 db/migration아래의 파일을 차례로 실행할 것이다. 하지만 두 번 롤백하고 20161111073930_xx_xx.rb를 제거하고 migration을 실행하고 그 후 20161111073930_xx_xx.rb를 되돌려 실행하면 잘 할 수 없다고 생각했지만 아무것도 변하지 않았다.
하지만 db/migration의 한 migration 파일을 실행했는지 여부라는 기록이 분명 다른 곳에 있다는 것을 알았다. 파일명만으로 결정하는 것이 아니다.
migration 테이블 수정
mysql> use auction_staging;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_auction_staging |
+---------------------------+
| ar_internal_metadata |
| xxx_results |
| xxx |
| schema_migrations |
| .... |
+---------------------------+
11 rows in set (0.00 sec)
mysql> select * from schema_migrations;
+----------------+
| version |
+----------------+
| 20160826080803 |
| 20160929044948 |
| 20160929045000 |
| 20160929045041 |
| 20161111073930 |
| 20161116033102 |
| 20161116105100 |
+----------------+
12 rows in set (0.00 sec)
과연, 20161111073930이라는 row를 지울 수 있는, 반드시 롤백을 할 수 있을 것!
select * from schema_migrations where version = '20161111073930';
delete from schema_migrations where version = '20161111073930';
두 번 롤백하고 migration하면 고쳤습니다!
RACK_ENV=staging bundle exec rake db:rollback STEP=2
RACK_ENV=staging bundle exec rake db:migration
마지막
@jhoshina 다양한 조언 해 주셔서 감사합니다! 살아났습니다!
Reference
이 문제에 관하여(중간 migration을 한 번 더 실행시키는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/arthurbryant/items/5930e93940c59a22eb1c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)