php 8.5 本身不内置读写分离能力,需依赖框架(如 laravel、thinkphp)或手动封装 pdo 实现;laravel 通过 'read'/'write' 配置自动路由,tp8 需启用 deploy 和 rw_separate 开关,手动 pdo 则需显式选择连接;主从延迟、事务一致性、健康检查及持久连接优化是关键注意事项。

PHP 8.5 本身不内置读写分离能力,它依赖框架或扩展来实现。配置读写分离的关键不在 PHP 版本,而在于你使用的数据库访问层(如 Laravel、ThinkPHP、PDO 手动封装等)。下面以主流实践方式说明核心配置逻辑和注意事项。
用 Laravel 实现读写分离
Laravel 原生支持读写分离,只需在 .env 和 config/database.php 中正确配置连接组:
- 在
.env中定义主从连接信息:DB_CONNECTION=mysqlDB_HOST=192.168.1.10(主库)DB_READ_HOST=192.168.1.11,192.168.1.12(多个从库,用逗号分隔)DB_PORT=3306 - 在
config/database.php的mysql连接配置中,把'read'和'write'拆开:'read' => ['host' => explode(',', env('DB_READ_HOST', '127.0.0.1'))],'write' => ['host' => env('DB_HOST', '127.0.0.1')],
Laravel 会自动将SELECT发往read组,其余操作走write。 - 注意:从库地址必须是数组,即使只有一个也要写成
['192.168.1.11'];主库不能出现在read列表里,否则可能造成脏读。
用 ThinkPHP 8.0 + Env 动态控制
TP8 不靠配置文件自动识别读写,需手动注入环境变量并启用部署开关:
- 在
.env中添加:DB_DEPLOY=1DB_RW_SEPARATE=true - 在
config/database.php的'mysql' => [...]内部设置:'deploy' => (int)Env::get('DB_DEPLOY', 0),'rw_separate' => filter_var(Env::get('DB_RW_SEPARATE', 'false'), FILTER_VALIDATE_BOOLEAN),
⚠️ 必须放在connections['mysql']配置块内,放错位置会导致失效。 - 从库列表通过
'read' => [['host' => 'xxx', 'port' => 3306]]显式声明;若DB_DEPLOY=0,'read'可为空数组,但启用时必须是非空二维数组。
手动封装 PDO 实现轻量级分离
适合无框架项目或需要精细控制的场景:
- 初始化两个 PDO 实例:
$writePdo = new PDO("mysql:host={$masterHost};dbname={$db}", $user, $pass);$readPdo = new PDO("mysql:host={$slaveHost};dbname={$db}", $user, $pass); - 封装一个简单路由函数:
function db($type = 'read') { return $type === 'write' ? $writePdo : $readPdo; } - 执行时显式选择:
db('read')->query("SELECT * FROM users WHERE id = 1");db('write')->exec("UPDATE users SET status = 1 WHERE id = 1");
关键注意事项
无论用哪种方式,以下几点直接影响稳定性:
- 主从延迟必须可控——尤其在写入后立刻读取的场景,建议对关键操作加
/*+ read_master */注释或强制走主库 - 事务中所有查询都应走主库,避免从库不可见未提交变更;Laravel/TP8 默认已处理,但自定义 PDO 需手动保证
- 健康检查机制不可少:定期 ping 从库,异常时自动剔除,恢复后再加入
- PHP 8.5 的 JIT 和协程(如 Swoole)对长连接更友好,建议开启
PDO::ATTR_PERSISTENT并配合连接池使用
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











