2026年10月13日
2026年10月13日
WordPressのデータベースをレプリケーションで冗長化する方法
はじめに
WordPressサイトの規模が拡大するにつれ、データベースの単一障害点(SPOF)は深刻なリスクとなります。MySQL/MariaDBのレプリケーション機能を活用してプライマリ・レプリカ構成を構築することで、データベース障害時のダウンタイムを最小化し、読み取りクエリの負荷分散も実現できます。本記事では、WordPressのHyperDBプラグインを使った実践的な冗長化手順を解説します。
症状・原因
- データベースサーバーの単一障害でサイト全体がダウンする
- 大量の読み取りクエリでDBサーバーのCPU使用率が100%に達する
- バックアップ取得中にパフォーマンスが著しく低下する
- 読み取り処理と書き込み処理を同一サーバーで処理している
- ディザスタリカバリ(DR)計画が存在しない
解決手順
ステップ1:プライマリサーバーのMySQL設定
プライマリ(マスター)サーバーの /etc/mysql/mysql.conf.d/mysqld.cnf を編集します。
# /etc/mysql/mysql.conf.d/mysqld.cnf の設定
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_expire_logs_secs = 2592000
max_binlog_size = 100M
binlog_format = ROW
# WordPressのDBのみレプリケーション対象にする場合
binlog_do_db = wordpress_db
# パフォーマンス設定
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
# 設定反映
# sudo systemctl restart mysql
# レプリケーション用ユーザー作成
# mysql -u root -p で接続後:
# CREATE USER 'replicator'@'%' IDENTIFIED BY 'StrongPass123!';
# GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%';
# FLUSH PRIVILEGES;
# SHOW MASTER STATUS; -- File と Position をメモする
ステップ2:レプリカサーバーのMySQL設定
レプリカ(スレーブ)サーバーに同様の設定を行います。
# /etc/mysql/mysql.conf.d/mysqld.cnf の設定(レプリカ側)
[mysqld]
server-id = 2
relay-log = /var/log/mysql/mysql-relay-bin.log
log_bin = /var/log/mysql/mysql-bin.log
read_only = ON
super_read_only = ON
# プライマリのデータをダンプ&インポート
# プライマリ側: mysqldump -u root -p --single-transaction --master-data=2 wordpress_db > dump.sql
# レプリカ側: mysql -u root -p wordpress_db < dump.sql
# レプリカの設定(mysql コンソールで実行)
# CHANGE MASTER TO
# MASTER_HOST='192.168.1.10',
# MASTER_USER='replicator',
# MASTER_PASSWORD='StrongPass123!',
# MASTER_LOG_FILE='mysql-bin.000001',
# MASTER_LOG_POS=154;
# START SLAVE;
# SHOW SLAVE STATUS\G -- Seconds_Behind_Master が 0 になるまで確認
ステップ3:HyperDBのインストールと設定
WordPressのHyperDBドロップインを使って読み書き分離を実装します。
<?php
// wp-content/db.php に HyperDB を配置後
// wp-config.php の直前に以下を追加
// db-config.php を wp-config.php と同じ階層に配置
// db-config.php の内容:
$wpdb_config = [
'primary' => [
'host' => '192.168.1.10', // プライマリDB
'user' => DB_USER,
'password' => DB_PASSWORD,
'name' => DB_NAME,
'write' => 1,
'read' => 0, // プライマリは書き込み専用
'dataset' => 'global',
'timeout' => 0.2,
],
'replica' => [
'host' => '192.168.1.20', // レプリカDB
'user' => DB_USER,
'password' => DB_PASSWORD,
'name' => DB_NAME,
'write' => 0, // レプリカは読み取り専用
'read' => 1,
'dataset' => 'global',
'timeout' => 0.2,
],
];
$hyperdb->add_database( $wpdb_config['primary'] );
$hyperdb->add_database( $wpdb_config['replica'] );
ステップ4:レプリケーション監視の実装
レプリケーションの遅延を自動検知するWordPressカスタム関数を実装します。
<?php
// functions.php または mu-plugins に追加
/**
* レプリケーション遅延を監視する
* wp_schedule_event で定期実行
*/
function wpdr_check_replication_lag() {
$replica_host = '192.168.1.20';
$replica_user = DB_USER;
$replica_pass = DB_PASSWORD;
$mysqli = new mysqli( $replica_host, $replica_user, $replica_pass );
if ( $mysqli->connect_error ) {
wpdr_send_alert( 'レプリカDBへの接続失敗: ' . $mysqli->connect_error );
return;
}
$result = $mysqli->query( 'SHOW SLAVE STATUS' );
$status = $result->fetch_assoc();
$lag = (int) $status['Seconds_Behind_Master'];
$io_running = $status['Slave_IO_Running'];
$sql_running = $status['Slave_SQL_Running'];
if ( 'Yes' !== $io_running || 'Yes' !== $sql_running ) {
wpdr_send_alert( 'レプリケーション停止: IO=' . $io_running . ', SQL=' . $sql_running );
} elseif ( $lag > 30 ) {
wpdr_send_alert( 'レプリケーション遅延: ' . $lag . '秒' );
}
update_option( 'wpdr_last_lag', $lag );
update_option( 'wpdr_last_check', current_time( 'mysql' ) );
$mysqli->close();
}
function wpdr_send_alert( string $message ): void {
wp_mail(
get_option( 'admin_email' ),
'[警告] DB レプリケーション異常',
$message . "\n\nサイト: " . get_site_url()
);
}
// 5分ごとに監視を実行
add_action( 'wpdr_monitor_hook', 'wpdr_check_replication_lag' );
if ( ! wp_next_scheduled( 'wpdr_monitor_hook' ) ) {
wp_schedule_event( time(), 'five_minutes', 'wpdr_monitor_hook' );
}
ステップ5:フェイルオーバー処理の実装
プライマリ障害時に自動的にレプリカへ切り替えるフェイルオーバー処理を設定します。
<?php
// wp-content/db.php のカスタムフェイルオーバー設定
/**
* プライマリDB障害時のフェイルオーバー
* HyperDB の callback 機能を利用
*/
function wpdr_failover_callback( $hyperdb ) {
// プライマリへの接続試行が失敗した場合
$failure_key = 'wpdr_primary_failure_count';
$failure_count = (int) get_transient( $failure_key );
if ( $failure_count >= 3 ) {
// プライマリを無効化し、レプリカを読み書き両用に昇格
$hyperdb->add_database([
'host' => '192.168.1.20',
'user' => DB_USER,
'password' => DB_PASSWORD,
'name' => DB_NAME,
'write' => 1, // レプリカを書き込み可能に変更
'read' => 1,
'dataset' => 'global',
'timeout' => 0.2,
]);
// 管理者へ通知
error_log( '[CRITICAL] WordPress DB フェイルオーバー実行: レプリカをプライマリに昇格' );
set_transient( 'wpdr_failover_active', true, HOUR_IN_SECONDS );
} else {
set_transient( $failure_key, $failure_count + 1, 300 );
}
}
注意事項
- レプリカへの書き込みは絶対に行わないこと。
super_read_only = ONを必ず設定し、誤操作によるデータ不整合を防ぐ - フェイルオーバー後は速やかにプライマリを復旧し、レプリカを元の役割に戻す。レプリカを長期間プライマリとして運用するとデータが失われるリスクがある
binlog_format = ROWを使用すること。STATEMENT形式は非決定的SQL(NOW(),RAND()等)でデータ不整合が発生する可能性がある- HyperDBはWordPress.orgの公式リポジトリからダウンロードし、必ずバージョンを確認してから本番環境に適用すること
- レプリケーション遅延(
Seconds_Behind_Master)が常に高い場合、バイナリログのI/O速度やネットワーク帯域を確認する
まとめ
MySQL/MariaDBのプライマリ・レプリカ構成とHyperDBを組み合わせることで、WordPressのデータベース冗長化と読み取り負荷分散を同時に実現できます。次のステップとして「WordPressを高可用性クラスター構成で運用する方法」も参照し、さらに堅牢なインフラ構築を検討してください。