2025.08.29
Laravelで空判定にif文を使うとハマる理由
2018.11.20
プログラミングSpringでMaster/Slave構成のMySQLに接続する(with Kotlin)

こんにちは、MTです。
今回は、Master/Slave構成のMySQLに接続する方法についてです。
(具体的には、クエリの発行先をMasterとSlaveで切り替える方法について)
■言語
・Kotlin 1.3.0
■アプリケーション
・SpringBoot 2.1.0
・mysql-connector-java 5.1.45
■MySQL 5.6
・Masterのホスト : localhost:3306
・Slave のホスト : localhost:3307
なお、MySQL自体のレプリケーション設定については触れていません。
通常はurlに指定するのは jdbc:mysql://スキームですが、Master/Slave構成の場合は jdbc:mysql:replication:// スキームを使用します。
そして jdbc:mysql:replication:// スキームに続けて、Masterのホストアドレス、Slaveのホストアドレスの順にカンマ区切りで記載していきます。
spring:
datasource:
driver-class-name: "com.mysql.jdbc.Driver"
url: "jdbc:mysql:replication://localhost:3306,localhost:3307/dev"
username: "dev"
password: "password"
こんな感じ。(末尾の /dev はデータベース名。) Slaveの指定は複数でもOKです。
宣言的トランザクションを利用している場合、readOnly オプションに true を指定すれば Slave に向きます。
@Transactional(readOnly = true) fun findAllBySlave(): List<User> = this.userRepository.findAll()
明示的トランザクションを利用する場合は、 java.sql.Connection インタンスを取得し、setReadOnly メソッドに true を設定してください。
事前に以下の user テーブルを作成し、MasterとSlaveで異なるデータを登録しておきます。
CREATE TABLE IF NOT EXISTS user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Master側
INSERT INTO user (name) VALUES ("user1"), ("user2"),( "user3");
-- Slave側
INSERT INTO user (name) VALUES ("user4"), ("user5"),( "user6");
次にデータを取得するサービス層で、宣言的トランザクションを利用して、読み取り専用とするかを定義しておきます。
@Service
class UserService(private val userRepository: UserRepository) {
@Transactional(readOnly = false)
fun findAllByMaster(): List<User> = this.userRepository.findAll()
@Transactional(readOnly = true)
fun findAllBySlave(): List<User> = this.userRepository.findAll()
}
ユーザ情報を取得するためのエンドポイントは以下のようにしました。
・/master : Master側に登録されたユーザ情報を取得する。
・/slave : Slave側に登録されたユーザ情報を取得する。
ではアクセスしてみます。
$ curl localhost:8080/master
[{"id":1,"name":"user1"},{"id":2,"name":"user2"},{"id":3,"name":"user3"}]
$ curl localhost:8080/slave
[{"id":1,"name":"user4"},{"id":2,"name":"user5"},{"id":3,"name":"user6"}]
ちゃんと向き先が変わってますね。
spring:
datasource:
driver-class-name: "com.mysql.jdbc.Driver"
url: "jdbc:mysql:replication://localhost:3306,localhost:3307/dev"
username: "dev"
password: "password"
@RestController
@SpringBootApplication
class MysqlReplicationSandboxApplication
constructor(private val service: UserService) {
@RequestMapping("master")
fun getByMaster(): List<User> = this.service.findAllByMaster()
@RequestMapping("slave")
fun getBySlave(): List<User> = this.service.findAllBySlave()
companion object {
@JvmStatic
fun main(args: Array<String>) {
SpringApplication.run(MysqlReplicationSandboxApplication::class.java, *args)
}
}
}
@Entity
data class User (
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long,
val name: String
): Serializable
@Service
class UserService(private val userRepository: UserRepository) {
@Transactional(readOnly = false)
fun findAllByMaster(): List<User> = this.userRepository.findAll()
@Transactional(readOnly = true)
fun findAllBySlave(): List<User> = this.userRepository.findAll()
}
@Repository
interface UserRepository : JpaRepository<User, Long>
version: '3.1'
services:
db1:
image: mysql:5.6
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD : "password"
MYSQL_DATABASE: "dev"
MYSQL_USER: "dev"
MYSQL_PASSWORD: "password"
volumes:
- ./mysql/init_master/:/docker-entrypoint-initdb.d
db2:
image: mysql:5.6
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD : "password"
MYSQL_DATABASE: "dev"
MYSQL_USER: "dev"
MYSQL_PASSWORD: "password"
volumes:
- ./mysql/init_slave/:/docker-entrypoint-initdb.d
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
1
2025.08.29
Laravelで空判定にif文を使うとハマる理由
2

2025.08.29
Git SSH接続でfetch/pullができなくなった時の対処法
3

2025.08.28
【体験談】Amazon Linux 2でMySQLインストール時のOpenSSL・GPG key エラーにハマった話
4
2025.08.28
【AWS】SSMポートフォワーディングとInstance Connectを利用したプライベートEC2へのSSH接続手順
5
2025.07.24
Log::info()が使えない!?Laravel.logのPermission denied エラーを解決する(Docker環境)
タグ検索