TP6中模型自动复用容器管理的连接,Query构造器需手动指定连接;模型支持useReadConnection()继承读库声明,Db查询器每次需显式调用Db::connect()或setConnectConfig()。

TP6 中 Query 构造器(如 Db::table())和模型(如 User::where())在连接复用机制上存在本质差异:前者依赖手动配置与显式声明,后者由容器自动管理并默认复用连接实例。
Query 构造器不自动复用连接上下文
直接使用 Db::table('user') 或 Db::connect('mysql_read') 创建的查询器是“一次性的”,它不会继承控制器或事务中的连接状态,也不会自动延续前序操作的读写分离意图。
- 调用
Db::connect('mysql_read')后,后续所有Db::table()操作仍走默认连接,因为模型/查询器之间不共享连接上下文 - 在事务中执行
select()会自动降级到主库——这是 TP6 的安全策略,不是 bug,但容易被误认为“连接没切过去” - 若在数据库中间件里调用
Db::setConnectConfig()却未配Db::close(),旧连接可能被复用,导致配置残留、读写错乱
模型操作天然复用容器管理的连接
模型类(继承 think\Model)由容器实例化,其底层查询器在初始化时就绑定到当前应用生命周期内的数据库连接实例,具备自动复用能力。
- 同一请求中多次调用
User::where()->find(),底层共用同一个连接对象,无需重复握手 - 模型支持
useReadConnection()显式声明读操作,且该声明可被后续链式方法继承(如User::useReadConnection()->where()->order()->select()) - 事务内模型操作(如
User::startTrans()后的save())自动沿用主库连接,无需额外干预
关键区别在于“谁控制连接生命周期”
Query 构造器把连接选择权交给开发者,适合临时、跨库、非标准场景;模型则把连接交由容器统一调度,更适合业务主流程,也更契合 TP6 的 PSR-15 中间件规范和连接池优化逻辑。
如果你需要读写分离生效,对模型务必加 ->useReadConnection();对 Db 查询器,则必须在每次查询前明确指定或切换连接,不能依赖“前面用过就读库”这种假设。

















