README.md in strong_migrations-0.5.1 vs README.md in strong_migrations-0.6.0

- old
+ new

@@ -1,9 +1,11 @@ # Strong Migrations Catch unsafe migrations in development +Supports for PostgreSQL, MySQL, and MariaDB + :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource) [![Build Status](https://travis-ci.org/ankane/strong_migrations.svg?branch=master)](https://travis-ci.org/ankane/strong_migrations) ## Installation @@ -84,11 +86,11 @@ 4. Deploy and run migration ### Adding a column with a default value -Note: This operation is safe in Postgres 11+. +Note: This operation is safe in Postgres 11+, MySQL 8.0.12+, and MariaDB 10.3.2+ #### Bad Adding a column with a default value to an existing table causes the entire table to be rewritten. @@ -142,14 +144,14 @@ ```ruby class BackfillSomeColumn < ActiveRecord::Migration[6.0] disable_ddl_transaction! - def change + def up User.unscoped.in_batches do |relation| relation.update_all some_column: "default_value" - sleep(0.1) # throttle + sleep(0.01) # throttle end end end ``` @@ -179,12 +181,18 @@ add_index :users, :some_column, algorithm: :concurrently end end ``` -If you forget `disable_ddl_transaction!`, the migration will fail. Also, note that indexes on new tables (those created in the same migration) don’t require this. Check out [gindex](https://github.com/ankane/gindex) to quickly generate index migrations without memorizing the syntax. +If you forget `disable_ddl_transaction!`, the migration will fail. Also, note that indexes on new tables (those created in the same migration) don’t require this. +With [gindex](https://github.com/ankane/gindex), you can generate an index migration instantly with: + +```sh +rails g index table column +``` + ### Adding a reference #### Bad Rails adds an index non-concurrently to references by default, which is problematic for Postgres. @@ -612,40 +620,54 @@ StrongMigrations.error_messages[:add_column_default] = "Your custom instructions" ``` Check the [source code](https://github.com/ankane/strong_migrations/blob/master/lib/strong_migrations.rb) for the list of keys. -## Postgres-Specific Features +## Analyze Tables -### Analyze Tables - Analyze tables automatically (to update planner statistics) after an index is added. Create an initializer with: ```ruby StrongMigrations.auto_analyze = true ``` -### Lock Timeout +## Target Version -It’s a good idea to set a lock timeout for the database user that runs migrations. This way, if migrations can’t acquire a lock in a timely manner, other statements won’t be stuck behind it. Here’s a great explanation of [how lock queues work](https://www.citusdata.com/blog/2018/02/15/when-postgresql-blocks/). +If your development database version is different from production, you can specify the production version so the right checks are run in development. -```sql -ALTER ROLE myuser SET lock_timeout = '10s'; +```ruby +StrongMigrations.target_postgresql_version = "10" +StrongMigrations.target_mysql_version = "8.0.12" +StrongMigrations.target_mariadb_version = "10.3.2" ``` -There’s also [a gem](https://github.com/gocardless/activerecord-safer_migrations) you can use for this. +For safety, this option only affects development and test environments. In other environments, the actual server version is always used. -### Target Version +## Timeouts -If your development database version is different from production, you can specify the production version so the right checks are run in development. +It’s a good idea to set a long statement timeout and a short lock timeout for migrations. This way, migrations can run for a while, and if a migration can’t acquire a lock in a timely manner, other statements won’t be stuck behind it. +You can use: + ```ruby -StrongMigrations.target_postgresql_version = 10 # or 9.6, etc +StrongMigrations.statement_timeout = 1.hour +StrongMigrations.lock_timeout = 10.seconds ``` -For safety, this option only affects development and test environments. In other environments, the actual server version is always used. +Or set the timeouts directly on the database user that runs migrations. For Postgres, use: +```sql +ALTER ROLE myuser SET statement_timeout = '1h'; +ALTER ROLE myuser SET lock_timeout = '10s'; +``` + +Note: If you use PgBouncer in transaction mode, you must set timeouts on the database user. + +## Permissions + +We recommend using a [separate database user](https://ankane.org/postgres-users) for migrations when possible so you don’t need to grant your app user permission to alter tables. + ## Additional Reading - [Rails Migrations with No Downtime](https://pedro.herokuapp.com/past/2011/7/13/rails_migrations_with_no_downtime/) - [PostgreSQL at Scale: Database Schema Changes Without Downtime](https://medium.com/braintree-product-technology/postgresql-at-scale-database-schema-changes-without-downtime-20d3749ed680) @@ -660,10 +682,10 @@ - [Report bugs](https://github.com/ankane/strong_migrations/issues) - Fix bugs and [submit pull requests](https://github.com/ankane/strong_migrations/pulls) - Write, clarify, or fix documentation - Suggest or add new features -To get started with development and testing: +To get started with development: ```sh git clone https://github.com/ankane/strong_migrations.git cd strong_migrations bundle install