Question

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?

Was it helpful?

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
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top