codeigniter在database.php中通过多维数组定义多个数据库配置,如$db['default']、$db['mysql_slave']、$db['pgsql_log'],每组需正确设置dbdriver(如mysqli、postgre、sqlsrv)并确保对应php扩展已启用,避免驱动冲突与持久连接问题。

database.php 里怎么定义多个数据库配置
CodeIgniter 支持在 application/config/database.php 中用不同键名定义多组数据库连接,比如 $db['default']、$db['mysql_slave']、$db['pgsql_log']。关键不是“类型”本身,而是每组配置里的 dbdriver 值必须匹配对应驱动(如 mysqli、postgre、sqlsrv)。
常见错误是把 dbdriver 写成 mysql —— 这在 CI 3.x 中已弃用,必须改用 mysqli;PostgreSQL 必须设为 postgre,不是 pgsql;SQL Server 要用 sqlsrv(Windows)或 pdo + DSN(跨平台)。
-
dbdriver值必须与 PHP 已启用的扩展一致(如mysqli对应extension=mysqli) - 不同数据库类型之间不能共用
dbprefix或char_set,比如 PostgreSQL 默认用utf8可能报错,得改成utf8mb4或UTF8 - 如果某组配置没设
autoinit,后续加载时要手动传TRUE,否则对象不会自动初始化
加载时如何指定驱动类型不冲突
CI 不会自动识别你配的是什么数据库类型,它只按 dbdriver 值去调用对应驱动类。所以如果你同时配了 mysqli 和 postgre,只要它们的 dbdriver 值正确、PHP 扩展可用,就能并存。
但要注意:CI 3.x 的驱动类是单例模式,同一请求中多次加载不同 dbdriver 的数据库,可能触发 Unable to load the requested database driver 错误——本质是驱动类已被初始化过,无法二次注册。
- 解决办法:确保每个数据库组的
dbdriver值唯一,且对应扩展已启用 - 避免在同一个控制器里反复调用
$this->load->database('xxx', TRUE)多次,尤其跨类型时 - PostgreSQL 需额外确认
pg_connect()是否可用,CI 不会帮你检测扩展是否真能连上
跨类型查询时模型和查询构建器的限制
CI 的 Query Builder(即 Active Record)不是完全数据库无关的。比如 $this->db->limit() 在 MySQL 是 LIMIT,在 PostgreSQL 是 LIMIT ... OFFSET,但 CI 3.x 对 PostgreSQL 的支持较弱,limit() + offset() 组合可能生成无效 SQL。
更隐蔽的问题是字段别名、保留字处理、大小写敏感性——MySQL 默认忽略大小写,PostgreSQL 把双引号字段当大小写敏感,而 CI 的 select() 不自动加引号。
- 涉及多类型数据库时,建议关闭 Query Builder:
$this->db->query("SELECT * FROM table")更可控 - 不要依赖
insert_id():PostgreSQL 需显式RETURNING id,SQL Server 用SCOPE_IDENTITY(),CI 的封装不一定适配 - 事务跨库无效:
$this->db->trans_start()只作用于当前加载的数据库实例,不能跨mysqli和postgre
为什么 pconnect 设为 TRUE 容易出问题
持久连接(pconnect = TRUE)在混合数据库类型场景下风险很高。MySQLi 的持久连接池和 PostgreSQL 的 pg_pconnect() 行为不一致,而且 CI 没有为不同 dbdriver 维护独立连接池。
典型现象是:第一次加载 mysqli 正常,再加载 postgre 时复用前一个连接句柄,导致 Call to a member function query() on boolean 或直接 PHP 崩溃。
- 生产环境务必设
pconnect = FALSE,尤其跨类型时 - 如果真需要连接复用,用应用层连接池(如 PgBouncer / ProxySQL),而不是依赖 CI 的
pconnect - CI 3.1.11+ 对
pdo驱动的持久连接支持更好,但需显式配置 DSN,不能靠hostname/database自动拼接
最常被忽略的一点:CI 不校验你写的 dbdriver 值是否真实存在——写成 dbdriver => 'oracle' 也不会报错,直到第一次执行查询才崩。动手前先确认 phpinfo() 里对应扩展已启用,再测通一个最简 query("SELECT 1")。











