Rails 6 introduced a new functionality to configure and manage multiple databases in our application.
The best examples for multiple database configuration are:
- Primary replica configuration, where all writes are executed on the primary and all reads on replica database.
- Application has multiple databases to deal with.
For e.g, we store
ordersof user in one database and their
archivedorders in different database.
To set multiple databases in our Rails application we need to set our
database.yml as below
Here, we have created two databases
We have also added one replica to the
The reads for
primary database will be performed from
and writes from
secondary both reads and writes will be performed on
There can be cases when we want to block the writes on the database:
- While performing a read operation.
- While executing a code block or transaction.
Examples for this use case can be:
- Converting a database from a single DB to a primary/replica
As shown in the above example, if we try to split
secondary_database(for write operation) and
secondary_database_replica(for read operation).
- Switching between databases i.e., from primary to replica or replica to primary and want to make sure that writes are not performed on replica.
To tackle the above issue, Rails 6 added ability to block writes to a database, even if the database user has permission to write (the database is a primary and not a replica).
As per the above example, database user can perform write operation
But, if we call
while_preventing_writes and try to create a User using
User.create!, it will raise an exception.
If we are in read
role and call
while_preventing_writes, no error is raised
User.first, since we are not writing.
Rails internally identifies whether a query is a read or write.
So, when SQL queries like
UPDATE are executed and writes are blocked
ActiveRecord::StatementInvalid error will be raised.