Rails 6.1 adds support for role switching and sharding in database
source link: https://blog.saeloun.com/2021/01/08/rails-6-1-pre-database-connection-switching
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails 6.1 adds support for role switching and sharding in database
Jan 8, 2021 , by Alkesh Ghorpade 2 minute readRails 6.1 adds the ability to switch a role or shard for an application with multiple databases. This means it is possible to switch connections for one database instead of all databases globally.
To use this feature, we need to set the below config in our application.
config.active_record.legacy_connection_handling = false
Let’s say we have two databases, primary
and vehicles
.
And we have shards and replica configured for each of them in database.yml
as below:
production:
primary:
database: primary_database
adapter: mysql
primary_replica:
database: primary_database
adapter: mysql
replica: true
primary_shard_one:
database: primary_shard_one
adapter: mysql
primary_shard_one_replica:
database: primary_shard_one
adapter: mysql
replica: true
vehicles:
database: vehicles_database
adapter: mysql
vehicles_replica:
database: vehicles_database
adapter: mysql
replica: true
vehicles_shard_one:
database: vehicles_shard_one
adapter: mysql
vehicles_shard_one_replica:
database: vehicles_shard_one
adapter: mysql
replica: true
We have two models User
and Car
. User
is stored in the primary
database and
Car
in the vehicles
database.
The corresponding model and abstract classes will look as below:
# primary database
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
shard_one: { writing: :primary_shard_one, reading: :primary_shard_one_replica }
}
end
# User class
class User < ApplicationRecord
end
# vehicles database
class VehiclesRecord < ApplicationRecord
self.abstract_class = true
connects_to shards: {
default: { writing: :vehicles, reading: :vehicles_replica },
shard_one: { writing: :vehicles_shard_one, reading: :vehicles_shard_one_replica }
}
end
# Car class
class Car < VehiclesRecord
end
When legacy_connection_handling
is set to false, any abstract connection class will
be able to switch connections without affecting other connections.
Before
ActiveRecord::Base.connected_to(role: :reading) do
User.first # Reads from primary replica
Car.first # Reads from vehicles replica
VehiclesRecord.connected_to(role: :reading, shard: :shard_one) do
User.first # Reads from shard_one_replica of primary database
Car.first # Reads from shard_one_replica of vehicles database
end
ApplicationRecord.connected_to(role: :reading, shard: :shard_one) do
User.first # Reads from shard_one_replica of primary database
Car.first # Reads from shard_one_replica of vehicles database
end
end
In both the above VehiclesRecord.connected_to
and ApplicationRecord.connected_to
blocks the connection was changed to shard_one
of the corresponding database.
After
ActiveRecord::Base.connected_to(role: :reading) do
User.first # Reads from primary replica
Car.first # Reads from vehicles replica
VehiclesRecord.connected_to(role: :reading, shard: :shard_one) do
User.first # Reads from primary replica
Car.first # Reads from shard_one_replica of vehicles database
end
ApplicationRecord.connected_to(role: :reading, shard: :shard_one) do
User.first # Reads from primary_shard_one_replica
Car.first # Reads from vehicles_primary
end
end
As seen above, when we connect VehiclesRecord
to shard_one
only Car
queries
are executed on shard_one
whereas User
queries are executed on primary
database.
Summary
The addition of this granular switching is useful in cases like:
- Suppose
replica
orshard_one
is not configured forprimary
database. A connection is made toshard_one
andUser
queries are executed under theshard_one
block, then an error would be thrown. This is because the connection was changed globally across all databases. - If two shards
shard_one
andshard_two
are configured for both databases,user_a
exists onshard_one
anduser_b
onshard_two
. IfVehiclesRecord
connection is changed toshard_two
and we query foruser_a
under that block it will return incorrect result.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK