Help us understand the problem. What is going on with this article?

[Mysql]db:migrate時にadd_indexで失敗するとハマる

More than 1 year has passed since last update.

MysqlとPostgreSQLの意外な機能差

MysqlとPostgreSQLってどっちもオープンソースだし似たようなもんでしょ、と思っていたんだけど、体感できる差を知ってしまった。

Mysqlでは、トランザクションの最中にcreate indexしようとすると、その時点でcommitしてしまってトランザクションじゃなくなってしまう。

MySQL :: MySQL 5.1 リファレンスマニュアル :: 12.4.3 暗黙のコミットを引き起こすステートメント : http://ftp.nchu.edu.tw/MySQL/doc/refman/5.1/ja/implicit-commit.html

PostgreSQLはちゃんと処理してくれるらしい。
Transactional DDL in PostgreSQL: A Competitive Analysis - PostgreSQL wiki : https://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis

MySQLでTruncateはRollback出来るのか? | SRIA BLOG : http://www.sria.co.jp/blog/2014/08/mysql-can-do-rollback-truncate/

railsだと、下記のようなケースでこの差が顕在化する

add_indexのミス

Migrationを書くときに、

class CreateActionLogs < ActiveRecord::Migration
  def change
    create_table :action_logs do |t|
      t.integer :user_id
      t.string :log_type
      t.timestamps
    end
    add_index :action_logs, [:log_type, :log_type], length:64
  end
end

みたいなコードを書いたんだけど、このadd_indexの書き方はMysqlだと通らない(sqliteだと通る)
これをうっかり実行した結果、add_indexでエラーになってmigrationがとまってしまった。

mysqlでは、add_indexの手前のcreate tableの時点でコミットが行われてしまうけど、migration全体としては失敗しているので、rails的にはこのマイグレーションは実行していないものと認識される。
でも実際にはaction_logsテーブルはすでに作成されているので、add_index部分を直してdb:migrateしてもtable already existsでエラーになってしまう。
逆に、db:rollbackでaction_logsテーブルを削除しようとしても、まだ実行されていないマイグレーションと認識されるので、rollbackしてもらうことも出来ない。ハマり状態。

これがPostgreSQLだと、create tableも含めてトランザクション(DDLトランザクション)でひとまとめに扱ってくれるので、add_indexが失敗した時も、全部ロールバックしてくれるらしい。へー。

脱出方法

ちなみにこのハマり現象は、migrationファイルを一時的に書き換えてmigrateを通したあと、元に戻してrollback→migrateして正しい状態に戻すことが出来た。

class CreateActionLogs < ActiveRecord::Migration
  def change
#     いったんコメントアウトした状態でmigrateする
#    create_table :action_logs do |t|
#      t.integer :user_id
#      t.string :log_type
#      t.timestamps
#    end
    add_index :action_logs, [:log_type, :log_type], length:64
  end
end

railsのみんながMysqlじゃなくてPostgreSQLをすすめるのはこのへんに理由があるのかな。

admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。
https://admin-guild.slack.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away