mysqlscalaslickmaster-slaveslick-2.0

Sending writes to the mysql master and reads to slave in slick


With Slick and a Master/Slave set up with MySQL, how do I ensure writes (INSERT, UPDATE, etc) are sent to the master and reads (SELECT) are send to the slaves?


Solution

  • According to the MySQL docs on this, we need to set Connection#setReadOnly(true|false).

    A nice way to do this in slick is to add the following functions to your database code:

    /**
     * Runs a block of read only database code. No transaction required.
     */
    def readOnly[T](f: => T) = db withSession {
      Database.threadLocalSession.conn.setReadOnly(true)
      f
    }
    
    /**
     * Runs a block of read/write database code in a transaction. 
     * Any exceptions will rollback any writes.
     */
    def readWrite[T](f: => T) = db withTransaction {
      Database.threadLocalSession.conn.setReadOnly(false)
      f
    }
    

    Then you can write queries like so:

    /**
     * Goes to slave
     */
    def findUser(id: String) = readOnly {
      sql"SELECT ... FROM user WHERE id = $id".as[User].firstOption
    }
    
    /**
     * Goes to master
     */
    def createUser(id: String) = readWrite {
      sqlu"INSERT INTO user VALUES(...)".execute
    }