netsket/sf-doctrine-master-slave-plugin

Easily manage master and slave database connections

Installs: 7 294

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 4

Forks: 0

Open Issues: 0

Type:symfony1-plugin

v1.0.2 2015-04-21 05:24 UTC

This package is auto-updated.

Last update: 2024-04-05 07:43:39 UTC


README

The `sfDoctrineMasterSlavePlugin` plugin manages database connections and
directs queries to the appropriate connection: either the master or a slave
database.

Once the plugin is enabled you can mark a connection as the master connection
in `databases.yml` by using the string "master" in its name:

    all:
      master:
        class: sfDoctrineDatabase
        param:
          dsn:      mysql:dbname=database;host:master.example.com
          username: root
          password: ~
      slave:
        class: sfDoctrineDatabase
        param:
          dsn:      mysql:dbname=database;host:slave.example.com
          username: root
          password: ~

Alternatively, you can provide an `is_master` parameter in the configuration:

    all:
      doctrine:
        class: sfDoctrineDatabase
        param:
          dsn:       mysql:dbname=database;host:master.example.com
          username:  root
          password:  ~
          is_master: true

If no connection is marked as the master connection using either of these
techniques, the first connection configured first will be used. If multiple
connections are marked as master, only the last connection marked will be used
as the master connection; the others will be used as slaves.

If your configuration includes more than one slave database, the plugin will
select one of them at random to use for the duration of the request.

Accessing the right connection
------------------------------

You can access the master or slave connections from the configuration object:

    [php]
    ProjectConfiguration::getActive()->getMasterConnection();
    ProjectConfiguration::getActive()->getSlaveConnection();

The plugin interacts with Doctrine as your database connection objects are
created and updates the current connection set in the `Doctrine_Manager` to
be the master connection. This way, any calls to
`Doctrine_Manager::connection()` will return the master connection, which is
usually what you need when calling that method (i.e. when beginning a
transaction).

>**NOTE**
>The slave database accessor `->getSlaveConnection()` includes logic to check
>whether the master database has any open transactions, and will return the
>master connection in that case.

Choosing from multiple slaves
-----------------------------

If you have multiple slave connections configured in `databases.yml`, the
plugin will choose one at random to use for the duration of the current
request. If you want to customize the logic surrounding how a slave connection
is selected, you can do so by listening to the `doctrine.select_slave` event.

    /** Listens to the doctrine.select_slave event. */
    public function selectSlave(sfEvent $event)
    {
      if (in_array('slave1', $event['slaves]))
      {
        $event->setReturnValue('slave1');
        return true;
      }
    }

The `doctrine.select_slave` event includes the following parameters:

  * `group`:  The group to select a slave connection from
  * `master`: The name of the master connection
  * `slaves`: An array of slave connection names

Notice this event receives the names of connections as parameters, not the
connection objects themselves. You can access the connection objects in your
event listener by calling
`Doctrine_Manager::getInstance()->getConnection($name)`.

Connecting to multiple schemas
------------------------------

If your schema assigns different connections to different models, you will
need to organize the master and slave connections for each of these schema
into groups using the `group` parameter:

    all:
      # db1 connections
      db1_master:
        class: sfDoctrineDatabase
        param:
          dsn:      mysql:dbname=db1;host:db1-master.example.com
          username: root
          password: ~
          group:    db1
      db1_slave:
        class: sfDoctrineDatabase
        param:
          dsn:      mysql:dbname=db1;host:db1-slave.example.com
          username: root
          password: ~
          group:    db1

      # db2 connections
      db2_master:
        class: sfDoctrineDatabase
        param:
          dsn:      mysql:dbname=db2;host:db2-master.example.com
          username: root
          password: ~
          group:    db2
      db2_slave:
        class: sfDoctrineDatabase
        param:
          dsn:      mysql:dbname=db2;host:db2-slave.example.com
          username: root
          password: ~
          group:    db2

Emulating read-only connections
-------------------------------

It's important to be able to test whether your connection management is
working correctly even when you're not connecting to any read-only databases.
The plugin provides a connection listener that emulates a read-only connection
for this purpose. Setup distinct master and slave connections in
`databases.yml` to enable this emulation in debug and test modes.

    dev:
      master: &master
        class: sfDoctrineDatabase
        param:
          dsn:       mysql:dbname=database;host=localhost
          username:  root
          password:  ~
      slave: *master