Rails has powerful sharding features available right within ActiveRecord.
It is possible to define either vertical or horizontal shards
and use connected_to
to switch between them.
When execution happens inside the method,
all database connections follow the configuration specified in the connected_to
block.
To configure our shards, we use the config/database.yml
file.
Here’s how ours looks.
development:
primary:
<<: *default
database: primary_database
primary_shard_two:
<<: *default
database: primary_shard_two
primary_shard_two_replica:
<<: *default
database: primary_shard_two
replica: true
Then we initiate the connection in ApplicationRecord.
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
shard_two: { writing: :primary_shard_two, reading: :primary_shard_two_replica }
}
end
Note that primary
and primary_shard_two
are not replicas of each other.
Rather, they are independent databases which share the same schema.
The primary_replica
and primary_shard_two_replica
are replicas.
Before
Originally two parameters were required for a connected_to
block – the name of the shard
and the role.
This was done to make it less syntactically confusing to use.
Let’s look at an example.
ActiveRecord::Base.connected_to(role: :reading, shard: :default) do
puts ActiveRecord::Base.connection_db_config.name
Blog.count
end
primary_replica
Blog Count (3.1ms) SELECT COUNT(*) FROM "blogs"
=> 3
However, if we don’t specify the role
parameter,
Rails throws an ArgumentError.
ActiveRecord::Base.connected_to(shard: :default) do
puts ActiveRecord::Base.connection_db_config.name
Blog.count
end
Traceback (most recent call last):
1: from (irb):1
ArgumentError (`connected_to` cannot accept a `shard` argument without a `role`.)
After
Changes to this PR remove the need for role to be passed to every connected_to
block.
This was done to prevent the need for a role
parameter from being passed
when execution was only concerned with the shared.
It also paves the way for more complex multi-tenancy work to be done later on while also simplifying calls for applications
that don’t use roles,
rather only have writer shards.