箱のプログラミング日記。

えんじにあ奮闘記

ActiveRecord::ConcurrentMigrationError:の対処法

capistranoでデプロイする過程でmigrationがエラーで実行できなかったのでメモ。

ActiveRecord::ConcurrentMigrationError

こんなエラーが出た

rake stderr: rake aborted!
ActiveRecord::ConcurrentMigrationError: 

Cannot run migrations because another migration process is currently running.

どうやら同じデータベース内で別のmigrationプロセスが走っているから実行できないよということらしい。

先ほど通信状況が悪く途中でCtrl+Cで終了させてしまったのがいけなかったっぽい。

プロセスをkill

mysqlにログインして現在走っているプロセスを確認してみる

mysql> SHOW PROCESSLIST;
+--------+-----------+---------------------+------------+---------+------+----------------+---------------------------------------------------------------------+
| Id     | User      | Host                | db         | Command | Time | State          | Info                                                                |
+--------+-----------+---------------------+------------+---------+------+----------------+---------------------------------------------------------------------+
| 248003 | hoge_user | 172.31.11.92:63986  | hoge_db    | Sleep   |    2 |                | NULL                                                                |
| 248004 | hoge_user | 172.31.11.92:63988  | hoge_db    | Sleep   |    5 |                | NULL                                                                |
| 248005 | hoge_user | 172.31.11.92:63990  | hoge_db    | Sleep   |    3 |                | NULL                                                                |
| 248006 | hoge_user | 172.31.11.92:63992  | hoge_db    | Sleep   |    5 |                | NULL                                                                |
| 248039 | hoge_user | 172.31.11.92:64058  | hoge_db    | Query   |  272 | altering table | ALTER TABLE `users` ADD `status` tinyint(1)                         |
| 248461 | hoge_user | 172.31.11.92:64358  | hoge_db   | Query   |    0 | init           | SHOW PROCESSLIST                                                    |
+--------+-----------+---------------------+------------+---------+------+----------------+---------------------------------------------------------------------+

こちらを一つずつ消していく

mysql> kill 248003;
Query OK, 0 rows affected (0.00 sec)

勢い余って最後のSHOW PROCESSLISTまで消そうとしてしまったのだけどちゃんとエラーになった

mysql> kill 248461;
ERROR 1317 (70100): Query execution was interrupted

Mysql2::Error: Duplicate column name

で、いざもう一度デプロイ(migration)を実行してみるとまた違うエラーが発生

rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Duplicate column name 'status': ALTER TABLE `users` ADD `status` tinyint(1)

すでにusersテーブルにstatusは存在するからカラム名が重複するものはADDできないよーということらしい。

おそらく先ほどmigrationのプロセスが途中だったので、すでにDBにカラムが追加されるところまで終わっていた可能性がある。

もう一度mysqlにログインしてDBを見てみると

mysql> show columns from users;
+---------------------+--------------+------+-----+---------+----------------+
| Field               | Type         | Null | Key | Default | Extra          |
+---------------------+--------------+------+-----+---------+----------------+
| id                  | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name                | varchar(255) | NO   |     | NULL    |                |
| created_at          | datetime     | NO   |     | NULL    |                |
| updated_at          | datetime     | NO   |     | NULL    |                |
| status              | tinyint(1)   | YES  |     | NULL    |                |
+---------------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

やっぱりあった。

migrationとDBの内容が食い違っている状態なので、手作業でmysql側を合わせていく(カラムを削除する)

mysql> alter table users drop column status;
Query OK, 0 rows affected, 2 warnings (21 min 48.04 sec)
Records: 0  Duplicates: 0  Warnings: 2

結構時間かかった^^;

で、もう一度migration実行したら今度はいけました。

参考

rails dbコマンドでConcurrentMigrationErrorが出た場合の対処法 - Qiita