0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】マイグレーションのbulk: trueとロールバック時の挙動について

Posted at

はじめに

Railsマイグレーションでbulk: trueを使って複数のカラムを追加した際のSQLログを比較し、挙動の違いを備忘録としてまとめます。検証環境はMySQLを前提としています。

結論

  • changeメソッドでbulk: trueを指定しても、ロールバック時には bulk: trueが効かず、カラムごとに個別のALTER TABLEが発行される
  • マイグレーションとロールバックの両方でbulk: trueを効かせ、処理をアトミックに実行したい場合は、up / downメソッドに分けて両方に bulk: trueを指定する

前提知識

DDL(Data Definition Language)

CREATE TABLE/ ALTER TABLE/DROP TABLEなど、スキーマ構造を変更するSQL

MySQLにおけるDDLの特徴

  • 実行時に暗黙的にコミットされる
  • 一つのDDL文はアトミックに実行される(全て成功するか、全て失敗するか)

bulkオプション

  • テーブル定義変更時に、複数の変更を1つのALTER TABLEにまとめるオプション
  • デフォルト値はfalse

実装例

1. changeメソッドの場合

結果: bulk: trueはマイグレーション実行時のみ有効

class AddColumnsOnSampleItems < ActiveRecord::Migration[6.1]
  def change
    change_table :sample_items, bulk: true do |t|
      t.integer :status_code
      t.string  :category_label
    end
  end
end

マイグレーション実行時

$ rails db:migrate
== 20250904070555 AddColumnsOnSampleItems: migrating ==========================
-- change_table(:sample_items, {:bulk=>true})
   -> 0.0755s
== 20250904070555 AddColumnsOnSampleItems: migrated (0.0757s) =================
(71.5ms)  ALTER TABLE `sample_items` ADD `status_code` int, ADD `category_label` varchar(255)

ロールバック実行時

$ rails db:rollback
== 20250904070555 AddColumnsOnSampleItems: reverting ==========================
-- remove_column(:sample_items, :category_label, :string)
   -> 0.0968s
-- remove_column(:sample_items, :status_code, :integer)
   -> 0.1003s
== 20250904070555 AddColumnsOnSampleItems: reverted (0.2016s) =================
(90.1ms)  ALTER TABLE `sample_items` DROP COLUMN `category_label`
(93.7ms)  ALTER TABLE `sample_items` DROP COLUMN `status_code`

2. up/downメソッド

結果: bulk: trueをマイグレーションとロールバックの両方に適用可能

class AddColumnsOnSampleItems < ActiveRecord::Migration[6.1]
  def up
    change_table :sample_items, bulk: true do |t|
      t.integer :status_code
      t.string  :category_label
    end
  end

  def down
    change_table :sample_items, bulk: true do |t|
      t.remove :status_code
      t.remove :category_label
    end
  end
end

マイグレーション実行時

$ rails db:migrate
== 20250904070555 AddColumnsOnSampleItems: migrating ==========================
-- change_table(:sample_items, {:bulk=>true})
   -> 0.0538s
== 20250904070555 AddColumnsOnSampleItems: migrated (0.0540s) =================
(49.1ms)  ALTER TABLE `sample_items` ADD `status_code` int, ADD `category_label` varchar(255)

ロールバック実行時

$ rails db:rollback
== 20250904070555 AddColumnsOnSampleItems: reverting ==========================
-- change_table(:sample_items, {:bulk=>true})
   -> 0.1045s
== 20250904070555 AddColumnsOnSampleItems: reverted (0.1092s) =================
(92.4ms)  ALTER TABLE `sample_items` DROP COLUMN `status_code`, DROP COLUMN `category_label`
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?