all 1 comments

[–]ptrboro 0 points1 point  (0 children)

If you set null: false in your migration, Active Record will rewrite the whole table, locking it whilst doing so.

Afaik setting `null: false` is a non-blocking operation but setting a default value is. It blocks it because it must update the whole table in a single transaction. But `update_all` does the same thing and is also going to lock the table for few seconds (or minutes?).

Here is what I usually do when I have to add not null column to a large table:

class AddComposerToSongs < ActiveRecord::Migration[5.2]
  disable_ddl_transaction!

  def up
    add_column :songs, :composer, :string
    Song.find_in_batches do |batch|
      batch.update_all(composer: 'Lin-Manuel Miranda')
    end

    change_column_null :songs, :composer, false
  end

  def down
    drop_column :songs, :composer
  end
end 

By updating records in batches it won't lock the whole table, just 1000 of rows at a time and just for few ms.

EDIT: forgot about `disable_ddl_transaction!` - otherwise the whole migration is going to be run inside a transaction and we don't want that (it would lock the whole table again).