README.textile in read_from_slave-0.4.0 vs README.textile in read_from_slave-0.5.0

- old
+ new

@@ -1,11 +1,13 @@ h1. Read_from_slave -h4. Read_from_slave for Rails enables database reads from a slave database, while writes continue to go to the master +h4. Read_from_slave for Rails enables database reads from one or more slave databases, while writes continue to go to the master Read_from_slave will work with Rails 2.2 and above, including Rails 3 versions. +Note that this version (0.5.x) supports multiple slave databases, but this caused an incompatibility in the configuration - your database.yml file must be updated before you can use this version. + h2. Installation <pre> <code> gem install read_from_slave @@ -24,30 +26,100 @@ In config/database.yml <pre> <code> -production: - adapter: mysql - database: mydatabase - username: myuser - password: mypassword - host: my.main.database.server.com - port: 3306 + production: + adapter: mysql + database: mydatabase + username: myuser + password: mypassword + host: my.main.database.server.com + port: 3306 + slaves: + primary_slave: slave_for_reads + slave_2: slave_for_reporting -slave_for_mydatabase: - adapter: mysql - database: mydatabase - username: myuser - password: mypassword - socket: /var/lib/mysql/mysql.sock + slave_for_reads: + adapter: mysql + database: mydatabase + username: myuser + password: mypassword + socket: /var/lib/mysql/mysql.sock + + slave_for_reporting: + adapter: mysql + database: mydatabase + username: myuser + password: mypassword + host: my.slave.database.server.com </code> </pre> Just use the regular YAML format to specify your slave database, it could equally well be on another server as the local example given above. +In the example above, primary_slave and slave_2 are names that are used to generate methods you can use to specify which slave to use. +slave_for_reads and slave_for_reporting is the yaml key that is used to make the connection to your slave database. + +You can have any number of slaves configured. To connect to the slaves: + +<pre> +<code> +ActiveRecord::Base.with_primary_slave do + User.last +end + +ActiveRecord::Base.with_slave_2 do + User.last +end +</pre> +</code> + +with_primary_slave and with_slave_2 are dynamically created based on the keys provided in the yaml file. Everything +inside the block with read from the corresponding slave database specified in the yaml file. + +You must have one slave with the primary_slave key. By default, all the reads will occur on the primary_slave, +in the example above, and not require you to use the with_primary_slave method. You actually never need to use +the with_primary_slave method as that slave will alwaysbe used if not inside a with... method block. So if you only have +1 slave, you don't ever need to worry about the with... methods. + +If you have multiple slaves, you will want to make sure you specify slave configurations for each environment, even if you +don't have slaves in every environment. + +<pre> +<code> +development: + adapter: mysql + database: mydatabase + username: myuser + password: mypassword + host: my.main.database.server.com + port: 3306 + slaves: + primary_slave: development + slave_2: development +</pre> +</code> + +The reason is, your code will have with_primary_slave and with_slave_2 methods because that is what you need in production, +but you will get undefined method errors in development because they won't be generated unless your development configuration +specifies slaves. Just specifying the slave keys back to the development configuration should serve your needs. + +You may have a need where you don't actually want all of your reads to be on the slave. You may want to be much more +selective in what you put on the slave. For instance, perhaps you want everything on the master except large reports. +You can change the default behavior of read_from_slave by setting: + +<pre> +<code> +ReadFromSlave.all_reads_on_slave = false +</pre> +</code> + +in your environment.rb file. This will make all reads on the master by default and reads will only be on the slave inside +the with... method blocks. + h2. Phusion Passenger Note that if you are using Passenger, you need to make sure that the slave database is reconnected if there is any chance that it was accessed before the spawner forks. This could be because database was accessed during the generation of routes, or perhaps if you are using the has_many_polymorphs @@ -90,14 +162,10 @@ 2057 tests, 6685 assertions, 0 failures, 0 errors </code> </pre> -h2. Todo - -* Support a pool of multiple slaves - h2. References * "Masochism":http://github.com/technoweenie/masochism/tree/master ** not thread safe ** won't work with apps that talk to multiple (master) databases @@ -110,5 +178,6 @@ ** looks like it won't work with apps that talk to multiple (master) databases ** more complex than read_from_slave (c) 2009 Stephen Sykes +Thanks to Kevin Tyll for contributing the multiple slave feature