EC-CUBEでデータベースをマスタースレーブ構成にするケースはよくあると思います。
EC-CUBE3で利用してるDoctrineには、MasterSlaveConnectionというConnectionのラッパークラスがあり、簡易的ではありますが、マスタースレーブ構成を実現することができます。
MasterSlaveConnectionの使い方は、Doctrine2 でレプリケーションする(マスタースレーブ構成) がとても参考になります。
EC-CUBEで利用する場合は、database.ymlの設定を以下のように記述します。
database:
wrapperClass: 'Doctrine\DBAL\Connections\MasterSlaveConnection'
driver: pdo_mysql
master:
host: 127.0.0.1
dbname: db_master
user: root
port: 33051
password: password
charset: utf8
defaultTableOptions: { collate: utf8_general_ci }
slaves:
slave1:
host: 127.0.0.1
dbname: db_slave1
port: 33052
user: root
password : password
charset: utf8
slave2:
host: 127.0.0.1
dbname: db_slave2
port: 33053
user: root
password : password
charset: utf8
これだけで、参照系クエリはスレーブに、更新系クエリはマスターに投げてくれます。
また、トランザクション中は参照・更新ともにマスターを見るようになります。
その他にも、スレーブではなくマスターを確実に参照したい、というようなケース(例えば在庫数とか)では、
$app['db']->connect('master');
をクエリ発行前に実行すると、以降はマスターを参照するようになります。
と、ここまで書いて、便利だなあと思ったのですが、EC-CUBE 3.0.11から、TransactionListenerという仕組みが導入されました。https://github.com/EC-CUBE/ec-cube/pull/1632
現状では、アプリケーションの起動終了のタイミングでトランザクションがかかるようになっており、MasterSlaveConnectionを使っても、マスターしか見ない状態になってしまいます。
Application.phpの以下の箇所をコメントアウトすれば、TransactionListenerを無効にでき、期待通りに動作します。
// add transaction listener
// TransactionListenerをコメントアウト
//$this['dispatcher']->addSubscriber(new TransactionListener($this));
ただこの機能を無効にすると全体に影響するため、少し扱いが難しいところです。。。
pgpoolのように、トランザクション中でも更新クエリ以降がマスターをみるようになっていればいいのですが、そこまでは残念ながら実装されていませんでした。
EC-CUBE3はsymfonyやdoctrineなど各種フレームワークに乗っかっており、こういった便利な機能も簡単に利用できるようになっています、というご紹介でした。