phalcon读写分离需手动配置di容器注册主从库服务,捕获从库连接异常并回退主库,事务中强制使用主库,多从库可轮询+故障跳过。

Phalcon 读写分离基础配置要到位
Phalcon 本身不内置读写分离逻辑,必须靠 DI 容器注册多个数据库服务,并在 Model 层手动控制路由。主库(dbWrite)和从库(dbRead)需分别注册为独立 service,且连接参数完整、数据库名一致(含大小写)。若从库用 VIP 或负载均衡地址,也建议单独配置,避免单点故障放大。
从库查询失败时不能静默崩掉
Phalcon 原生不检测从库可用性,也不自动重试或切主。一旦 $this->getReadConnection() 返回的从库连接失败(如 Connection refused、timeout),就会直接抛 PDOException。必须主动捕获:
- 在 Model 的 find/select 等方法外层加 try/catch,不要只包 SQL 执行部分
- 判断异常是否属于连接类错误(如包含 "Connection refused"、"Lost connection"、"timeout")
- 确认是读操作后,显式调用
$this->getWriteConnection()->query(...)回退主库执行 - 避免在循环中反复 new 连接或重复调 getReadConnection(),复用已有实例更稳定
事务与强一致性场景必须绕过从库
Phalcon 没有“事务内自动锁定主库”的机制。如果业务涉及写后立刻读、或同一事务中需多次读取,务必手动指定主库连接:
- 用
$this->getWriteConnection()替代$this->getReadConnection() - 在 initialize() 中统一设置
$this->setConnectionService('dbWrite'),适用于全表强一致读 - 避免在事务中先查从库再写主库——这会破坏一致性,也容易因连接切换引发异常
进阶:实现简单轮询+故障跳过
若配了多个从库但 Phalcon 默认只用一个(如 dbRead),可自行扩展读连接选择逻辑:
- 在基类 Model 中维护一个静态计数器,每次调
getReadConnection()时轮询下标 - catch 异常后递增下标并重试下一个从库,超限则 fallback 主库
- 不推荐在 onConstruct 或 initialize 中动态改 service 名,DI 容器已固化实例,运行时替换无效
- 真正需要高可用路由,建议前置引入 ProxySQL 或 MaxScale,让数据库层接管分流与健康检查











