お客さんのサイトのアクセスが最近10倍以上に増えてきました。ロードバランスもなく1台にウェブもDBもメールサーバーもあるAWSの仮想マシンなので、とりあえず、仮想マシンをアップグレードしました。

しかし、アップグレードしてもDBのトランザクションでデッドロックが起きるなどの問題が起こります。これはDBやOSのカーネルの調整が必要となるか、それともやはり、ロードバランスが必要なときか、しかしそんな専門的知識もないしそれを学習や試験する時間も必要だし。。。と悩んでいるときに、DBの読み書きでDB接続を自動的に使い分ける機能がLaravelにあることを見つけました。

DBの複製は、MySQLデータベースのレプリカにAWS RDSを利用で、すでに設定してあり、これをDBの読み込み専用に使います。書き込みは本マシンのマスターのDBを使います。

さて、Laravel側で変更することは以下のDB設定の変更です。まず、新規にmysql_rwなる接続を定義します。

...
        'mysql_rw' => [
            'write' => [ // 書き込み
              'host' => '127.0.0.1'
            ],
            'read' => [  // 読み込み専用、複製DB
              'host' => '127.0.0.2' // RDSのendpointのURLあるいはプライベートIPアドレス
            ],
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
...

上の例では、複製のDBのユーザーとパスワードはマスターのDBのユーザーと同じという仮定ですが、違うなら以下のようにも指定できます。

    'write' => [
        'host' => '127.0.0.1',
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
    ],
    'read' => [
        'host' => '127.0.0.2',
        'username' => env('DB_USERNAME_RO', env('DB_USERNAME')),
        'password' => env('DB_PASSWORD_RO', env('DB_PASSWORD')),
    ],

さらに、複製DBが1つでは足りないときは、複数の設定も可能です。

    'read' => [
        'host' => ['127.0.0.2', '127.0.0.3', '127.0.0.4'], 
        'username' => env('DB_USERNAME_RO', env('DB_USERNAME')),
        'password' => env('DB_PASSWORD_RO', env('DB_PASSWORD')),
    ],

最後に、.envを編集して、

...
DB_CONNECTION=mysql_rw
...

とDB接続を変更します。

By khino