本文目录导读:

在Laravel中配置MySQL读写分离非常简单,主要通过修改 config/database.php 实现,以下是完整配置方案:
基础配置(config/database.php)
'mysql' => [
'read' => [
'host' => [
'192.168.1.101', // 从库1
'192.168.1.102', // 从库2(可选)
],
],
'write' => [
'host' => [
'192.168.1.100', // 主库
],
],
'sticky' => true, // 读写粘性(可选)
'driver' => 'mysql',
'database' => 'your_database',
'username' => 'your_username',
'password' => 'your_password',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
],
完整配置示例(带多个从库)
'mysql' => [
// 读取(从库)配置
'read' => [
'host' => [
'192.168.1.101',
'192.168.1.102',
'192.168.1.103',
],
'port' => 3306,
],
// 写入(主库)配置
'write' => [
'host' => [
'192.168.1.100',
],
'port' => 3306,
],
// 公共配置(读写共享)
'driver' => 'mysql',
'database' => 'laravel_db',
'username' => 'app_user',
'password' => 'secure_password',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
// 连接池和粘性设置
'sticky' => true, // 同一请求内写入后读取使用主库
'prefix' => '',
// 高级配置
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
],
],
使用不同数据库名称的配置
如果主从库数据库名不同:
'read' => [
'host' => ['192.168.1.101'],
'database' => 'read_db', // 从库数据库名
],
'write' => [
'host' => ['192.168.1.100'],
'database' => 'write_db', // 主库数据库名
],
验证读写分离
// 在控制器或服务中测试
public function testReadWrite()
{
// 写入操作(会连接主库)
$user = new User();
$user->name = '测试用户';
$user->save();
// 读取操作(会连接从库)
$users = User::all();
// 查看实际连接的数据库
\DB::enableQueryLog();
User::find(1);
$queries = \DB::getQueryLog();
dd($queries); // 可以看到具体连接的数据库
}
使用.env配置(推荐)
# .env 文件 DB_HOST_MASTER=192.168.1.100 DB_HOST_SLAVE_1=192.168.1.101 DB_HOST_SLAVE_2=192.168.1.102 DB_DATABASE=laravel_db DB_USERNAME=app_user DB_PASSWORD=secret
然后在 config/database.php 中:
'read' => [
'host' => [
env('DB_HOST_SLAVE_1'),
env('DB_HOST_SLAVE_2'),
],
],
'write' => [
'host' => [
env('DB_HOST_MASTER'),
],
],
注意事项
-
sticky 选项:设为
true时,同一请求中写入后立即读取会使用主库,避免数据不一致 -
负载均衡:Laravel 会随机选择从库进行读取,实现简单的负载均衡
-
读写分离不适用于事务:在事务中所有操作都会使用主库
\DB::transaction(function () {
// 事务内所有操作都在主库执行
User::create([...]);
$user = User::find(1); // 这里也是主库
});
- 强制使用主库读取:
User::onWriteConnection()->find(1); // 强制使用主库
- 指定连接:
$users = DB::connection('mysql')->table('users')->get(); // 使用默认连接
查看当前使用的连接
// 查看当前连接配置
$connection = DB::connection();
dd($connection->getConfig());
// 查看执行的SQL及连接的数据库
\DB::listen(function ($query) {
dump($query->sql);
dump($query->connection->getDatabaseName());
});
通过以上配置,Laravel 会自动处理读写分离,无需手动干预。