6
votes

I'm using the Doctrine2 master/slave configuration in Symfony2 to scale my application across a single master database and several read-only (replicated) slaves.

This works perfectly from within my application and Doctrine2 sensibly uses the slave for read-only queries and the master for write operations.

If in one of my controllers, I wrote:

$em = $this->get('doctrine')->getManager();
var_dump($em->getConnection()->isConnectedToMaster());

isConnectedToMaster() returns false - which I would expect since the slave is connected to by default.

This is also the case if I run this code inside a WebTestCase

However if I wrote the exact same code inside a Symfony console command (ContainerAwareCommand):

$em = $this->getContainer()->get('doctrine')->getManager();
var_dump($em->getConnection()->isConnectedToMaster());

isConnectedToMaster() returns true. Which means the master is selected as the default.

I can't find out how to stop the default connection being master from console commands. Which means if I want to run some non-critical, heavy data processing tasks from the console - they all hit the master (bad) not one of the slaves (good).

Anyone know how I can make Doctrine2 use the slave by default from the console? Or know why it always defaults to the master?

ANSWERED: Thanks to nifr who set me on the right course - I found that my problem was because I was using JMS\JobQueueBundle (which replaces the Application used by app/console with an altered one which must connect to the MasterSlaveConnection in a way which forces the "master" to be chosen). When I commented out the

use JMS\JobQueueBundle\Console\Application;

in app/console, the slave was correctly selected in my console test.

Thanks

2

2 Answers

9
votes

You have to make sure your command doesn't call any action that lets doctrine choose the master connection.


Important for the understanding of the MasterSlaveConnection should be how and when it picks the slave or master.

  • picks Slave if Master was never picked before and ONLY if 'getWrappedConnection' or 'executeQuery' is used.
  • Master picked when 'exec', 'executeUpdate', 'insert', 'delete', 'update', 'createSavepoint', 'releaseSavepoint', 'beginTransaction', 'rollback', 'commit', 'query' or 'prepare' is called.
  • If master was picked once during the lifetime of the connection it will always get picked afterwards.
  • One slave connection is randomly picked ONCE during a request.

(MasterSlaveConnection API)

2
votes

I ended up on this question when I was looking for a way to query either my master for writting or my slaves for reading.

Here is the magic:

  • Write operations (use master): $em->getConnection->executeUpdate(...);

  • Read operations (use slaves): $em->getConnection->executeQuery(...);