ci中自定义类需用$this->load->database($config, true)创建独立数据库连接实例,不可复用默认$this->db;配置须完整且传入true参数,事务无法跨实例保证原子性,ci4需手动获取query builder。

CI 中如何让自定义类使用独立数据库连接而不是默认连接
CodeIgniter 默认所有数据库操作共享 $this->db 单例,但自定义类(比如服务类、模型类)若需同时操作多个数据库(如主库写、从库读、日志库单独写),必须显式创建并管理独立连接实例,否则会复用全局连接、导致事务污染或连接配置错乱。
关键点在于:不能直接用 $this->load->database() 在自定义类里调用(它仍返回全局实例),而应传入配置数组并设 'return' => TRUE。
-
$db1 = $this->load->database(['hostname' => '192.168.1.10', 'username' => 'user1'], TRUE);——TRUE表示返回新实例而非复用 - 配置项中必须包含完整连接参数(
hostname、username、password、database、dbdriver),缺一不可;即使只改 host,也要全量传入 - 避免在构造函数里硬编码配置——把配置名(如
'slave')作为参数传入,再从application/config/database.php的$db['slave']中提取,便于环境隔离
多数据库分组切换时,为什么 switch_db() 不生效
CI 没有内置 switch_db() 方法。常见错误是误以为调用 $this->db->close(); $this->load->database('other_group'); 就能切换,实际上 $this->load->database('other_group') 仍返回原实例(除非加 TRUE),且 close() 不会自动销毁旧连接句柄。
真正切换分组的唯一可靠方式是:每次需要不同库时,都新建一个带 TRUE 参数的连接实例,并保存为局部变量或类属性(如 $this->slave_db)。
- 不要试图“切换”同一个
$this->db实例——CI 的 DB 类设计不支持运行时重连 - 如果用
$this->load->database('group_name', TRUE)多次调用同一分组,CI 会复用已创建的实例(基于配置哈希),这是安全的 - 注意连接数限制:每个
TRUE实例都会占用一个 MySQL 连接,务必在不用时调用$db->close(),尤其在长生命周期的服务类中
自定义类里调用多个数据库时,事务怎么隔离
CI 的 $this->db->trans_start() 只作用于当前 DB 实例,跨实例事务无法统一提交或回滚。也就是说,如果你用 $db_master 和 $db_log 分别执行写操作,它们的事务完全独立,不存在原子性保障。
实际项目中只能做应用层补偿或降级处理,不能依赖数据库级分布式事务。
- 主库操作失败 → 立即中止,不执行日志库写入
- 主库成功但日志库失败 → 记录本地 error log,后续由定时任务重试日志写入
- 绝对不要在两个 DB 实例上调用
trans_start()后一起trans_complete()——这只会让两个事务各自按自己规则提交,毫无关联 - 如果强一致性要求高,应考虑合并到单库(用不同 schema 或前缀),而非拆分物理库
CI3 和 CI4 在多库连接上的主要差异
CI3 用 $this->load->database($config, TRUE) 创建独立实例,CI4 则通过 Config\Database::connect($group) 获取连接,且默认返回新实例(无需额外标志位),但 CI4 的 Query Builder 不自动绑定连接,需手动传入:
- CI3:
$db->select()->from('users')->get()——$db实例自带 Query Builder - CI4:
$builder = $db->table('users')->select()->get()——$db是 Connection 对象,Builder 需显式获取 - CI4 的
$db实例默认不开启 persistent 连接,CI3 需手动设'pconnect' => FALSE防连接泄漏 - CI4 支持更细粒度的连接池配置,但实际项目中多数仍用单例模式,多库场景下仍需手动管理多个
Connection实例
跨版本迁移时最容易忽略的是 Builder 绑定逻辑,CI3 代码直接挪到 CI4 会报 Call to undefined method 错误,因为 $db 不再是 Query Builder 的代理对象。











