EC-CUBEでデータベースをマスタースレーブ構成にするケースはよくあると思います。

EC-CUBE3で利用してるDoctrineには、MasterSlaveConnectionというConnectionのラッパークラスがあり、簡易的ではありますが、マスタースレーブ構成を実現することができます。

MasterSlaveConnectionの使い方は、Doctrine2 でレプリケーションする(マスタースレーブ構成) がとても参考になります。

EC-CUBEで利用する場合は、database.ymlの設定を以下のように記述します。

app/config/eccube/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を無効にでき、期待通りに動作します。

src/Eccube/Application.php
        // add transaction listener
        // TransactionListenerをコメントアウト
        //$this['dispatcher']->addSubscriber(new TransactionListener($this));

ただこの機能を無効にすると全体に影響するため、少し扱いが難しいところです。。。

pgpoolのように、トランザクション中でも更新クエリ以降がマスターをみるようになっていればいいのですが、そこまでは残念ながら実装されていませんでした。

EC-CUBE3はsymfonyやdoctrineなど各種フレームワークに乗っかっており、こういった便利な機能も簡単に利用できるようになっています、というご紹介でした。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.