ci多数据库连接需在database.php中用唯一键名定义多组连接,硬性字段缺一不可;model中必须用$this->load->database('key', true)获取独立实例,禁用$pconnect以防事务污染。

database.php 里定义多组连接要带唯一键名
在 application/config/database.php 中,$db 是个二维数组,每组连接必须用不同键名(如 'default'、'writedb'、'logdb'),不能重复或漏掉任何必填字段:
-
'hostname'、'username'、'password'、'database'、'dbdriver'这五个是硬性要求,少一个就会报Call to a member function query() on null - 不要只改
$active_group = 'writedb'就以为切换成功了——这只是控制「自动加载的默认连接」,不影响你手动加载其他组 - 如果要用 mysqli 而不是过时的 mysql,请明确写
'dbdriver' => 'mysqli',否则 CI2/3 可能静默失败
在 Model 或自定义类里加载指定连接必须传 TRUE
这是最常翻车的地方:$this->load->database('writedb') 默认返回全局 $this->db 实例(即单例),根本没新建连接;必须加第二个参数 TRUE 才生成独立实例:
- 正确写法:
$this->writedb = $this->load->database('writedb', TRUE); - 错误写法:
$this->writedb = $this->load->database('writedb');→ 后续所有操作其实还在default上 - 事务无法跨连接保证原子性:你在
$this->writedb上start_transaction(),跟$this->db的事务完全无关 - CI4 不兼容此写法,需改用
Database::connect('writedb'),且 Query Builder 需手动获取
读写分离场景下别让控制器“猜”该用哪个库
典型误操作是把 $this->db 直接塞进业务逻辑,结果写操作跑到了从库上,或者主库连接被读请求占满。推荐做法是显式拆分职责:
- 写操作统一走命名明确的实例,比如
$this->main_db->insert(),并在构造函数里固定加载'writedb' - 读操作可走
$this->slave_db = $this->load->database('slavedb', TRUE),配合负载均衡或随机选从 - 避免在同一个方法里混用多个连接实例做关联查询(比如 JOIN 跨库),MySQL 本身不支持,得靠应用层拼装
- 注意连接数限制:每个
TRUE实例都会占用一个 PHP 数据库连接,高并发下容易触发Too many connections
'pconnect' 设为 TRUE 时,多个独立实例可能意外共享底层 socket**,导致事务状态污染或字符集错乱。生产环境建议统一设为 FALSE,靠连接池或短连接管理更可控。











