codeigniter 的 failover 是为主数据库连接配置同结构冗余实例的自动故障转移机制,需在 database.php 中为连接组显式定义完整备用配置数组,仅在初始连接失败时按序尝试,ci4 已移除该功能。

CodeIgniter 的 failover 是为单个数据库连接组(如 $db['default'])配置备用连接的机制,不是跨库切换,而是当主数据库连不上时,自动尝试列表里的备用服务器——它们必须是**同库同结构、仅主机/凭证不同的冗余实例**(比如主从、镜像或高可用集群中的备节点)。
database.php 中正确配置 failover 数组
在 application/config/database.php 里,为某组连接(如 default)的 'failover' 键赋值一个含多个完整配置的数组。每个子数组都需包含全部必要字段,不能省略:
-
必须完整复制主连接的关键项:
'hostname'、'username'、'password'、'database'、'dbdriver'、'char_set'、'dbcollat'等,缺一不可; -
不继承主配置的其他设置:比如
'pconnect'或'db_debug'若未显式写出,不会自动取主组值; -
DSN 优先级说明:若主组用了
'dsn',failover 子项也建议统一用 DSN;若没写 DSN,CI 会按各子项自己的字段拼接,但务必确保字符集等参数已明确指定。
示例:
$db['default']['failover'] = array(
array(
'hostname' => '192.168.1.10',
'username' => 'app_user',
'password' => 'xxx',
'database' => 'myapp_db',
'dbdriver' => 'mysqli',
'char_set' => 'utf8mb4',
'dbcollat' => 'utf8mb4_unicode_ci',
'pconnect' => FALSE,
'db_debug' => FALSE
),
array(
'hostname' => '192.168.1.11',
'username' => 'app_user',
'password' => 'xxx',
'database' => 'myapp_db',
'dbdriver' => 'mysqli',
'char_set' => 'utf8mb4',
'dbcollat' => 'utf8mb4_unicode_ci',
'pconnect' => FALSE,
'db_debug' => FALSE
)
);
failover 触发时机与行为
CI 不会在每次查询前预检主库,而是在首次连接失败时触发 failover 流程:
- 调用
$this->load->database()时,CI 先尝试主配置连接; - 若连接失败(如 mysqli_connect() 报错、超时、拒绝),则按顺序逐个尝试
failover数组中的配置; - 任一 failover 成功,即使用该连接,并继续后续所有查询;
- 全部失败才抛出最终错误,应用终止或进入异常处理流程。
⚠️ 注意:failover 不处理查询执行中的错误(如 SQL 语法错、锁超时),只管连接建立阶段。
关键避坑点
-
不要混用 pconnect:多 failover 节点共用同一用户+端口时,开启
'pconnect' => TRUE可能导致连接资源复用混乱,建议统一设为FALSE; -
字符集必须显式一致:尤其 MySQL 类驱动,
'char_set'和'dbcollat'在每个 failover 项中都要写,否则可能因编码不匹配导致连接后查询乱码或失败; - 不支持嵌套或动态生成:failover 数组必须是静态定义在 config 文件中,运行时无法追加或修改;
-
CI3 有效,CI4 已移除:CodeIgniter 4 完全弃用了
failover键,改用自定义连接工厂或中间件实现类似逻辑。
替代方案(CI4 或更灵活场景)
若你用的是 CI4,或需要更精细控制(如按错误类型切换、带重试延迟、日志记录),推荐:
- 封装一个 DB 连接服务类,内部用
try/catch依次调用Config\Database::connect(); - 结合
PDO::ATTR_ERRMODE和具体异常类型(如PDOException)判断是否值得重试; - 加入指数退避(exponential backoff)避免雪崩重试;
- 将当前有效连接缓存到静态属性,减少重复探测开销。











