Laravel中如何查看当前请求使用的数据库读节点
Laravel PostgreSQL读写分离场景下确认实际命中的读节点方法
你调用$user->getConnection()拿不到读节点信息的核心原因是:Laravel的读写分离连接是懒加载的,只有真正执行读SQL时才会从配置的读节点列表中选定节点建立连接,且getConnection()返回的是连接管理器实例,本身不会暴露当前选中的具体读节点配置。
可通过以下两种方式精准获取当前请求命中的读节点:
方法1:单接口调试直接获取连接信息
在触发至少一次读查询后,通过PDO实例调用PostgreSQL内置函数获取实际连接的服务端信息,这是最准确的方式,不会被配置缓存干扰:
public function test(User $user) { // 先执行一次读查询,确保读连接已经完成初始化选点 $testUser = User::query()->first(); $connection = $testUser->getConnection(); // 获取当前读连接的PDO实例 $readPdo = $connection->getReadPdo(); // 调用PostgreSQL内置函数查询实际连接的服务端信息 $serverInfo = $readPdo->query('SELECT inet_server_addr() AS connected_host, inet_server_port() AS connected_port ')->fetch(); dd([ '配置内定义的所有读节点' => $connection->getConfig('read.host'), '当前实际命中的读节点IP' => $serverInfo->connected_host, '当前实际命中的读节点端口' => $serverInfo->connected_port ]); }
方法2:全局监听所有查询的节点命中情况
如果需要排查整个请求链路中所有读查询的节点分配情况,可以在服务提供者中注册数据库查询监听,自动记录每次读查询的命中节点:
// 在app/Providers/AppServiceProvider.php的boot方法中添加 public function boot() { \DB::listen(function ($query) { $connection = $query->connection; // 判断当前查询使用的是读连接而非写连接 $isUseReadNode = $connection->getPdo() !== $query->pdo; if ($isUseReadNode) { $connectedHost = $query->pdo ->query('SELECT inet_server_addr() AS host') ->fetch() ->host; // 调试时可直接输出,生产环境建议写日志 logger()->debug('读查询节点命中记录', [ 'sql' => $query->sql, 'hit_read_host' => $connectedHost, 'execute_time' => $query->time ]); } }); }
注意事项
- 不要在未执行任何读查询前尝试获取节点信息,此时Laravel还未选定读节点建立连接,拿不到有效数据
- Laravel默认开启
sticky模式,同一个请求中如果执行了写操作,后续所有读查询会自动路由到写节点,避免主从延迟导致读不到刚写入的数据,这种情况属于框架正常逻辑,不算读节点分配异常 - 不要依赖读取配置文件的方式判断命中节点,Laravel选节点时会做随机分配,配置值无法反映实际选中的节点
内容的提问来源于stack exchange,提问作者Mikaele
相关产品推荐
相关产品推荐

