SQLite内存数据库的DSN必须为sqlite::memory:,CodeIgniter 3仅识别此格式;需设subdriver为sqlite、database留空、调用initialize()验证连接,且内存库每次请求独立、不跨请求共享、无法使用dbforge和迁移类。

SQLite内存数据库的DSN写法必须是sqlite::memory:
CodeIgniter 3 不支持直接用 sqlite://:memory: 或其他变体,唯一被 PDO SQLite 驱动识别的内存数据库 DSN 是 sqlite::memory:(注意两个冒号,且没有斜杠)。填错就会报 unable to open database file,哪怕其他配置全对。
示例配置片段(放在 application/config/database.php 中):
$db['sqlite_mem'] = array( 'dsn' => 'sqlite::memory:', 'dbdriver' => 'pdo', 'subdriver' => 'sqlite', 'dbprefix' => '', 'pconnect' => FALSE, 'db_debug' => TRUE, 'cache_on' => FALSE, 'cachedir' => '', 'char_set' => 'utf8', 'dbcollat' => 'utf8_general_ci', 'swap_pre' => '', 'autoinit' => TRUE, 'stricton' => FALSE, 'failover' => array(), 'port' => '' );
-
subdriver必须显式设为sqlite,否则 PDO 无法确定子驱动类型 -
database字段必须留空或完全删除——填任何值都会干扰 DSN 解析 -
hostname、username、password全部不用设,也不应出现
加载后必须调用 initialize() 才算真正连上
仅执行 $this->load->database('sqlite_mem', TRUE) 只是初始化了 DB 类实例,不触发实际连接。内存数据库的连接延迟到第一次查询才建立,所以光看返回对象是否为真毫无意义。
验证方式必须是:
$db = $this->load->database('sqlite_mem', TRUE);
if ($db && $db->initialize()) {
// 连接成功,可以开始建表或插入
} else {
log_message('error', 'SQLite memory DB init failed');
}
- 用
@$db->initialize()抑制警告不可取——掩盖了权限或驱动缺失等真实问题 - 如果
initialize()返回FALSE,常见原因是subdriver没设,或 PHP 缺少pdo_sqlite扩展 - 内存库每次请求都是全新实例,不能跨请求共享数据
内存数据库没法用迁移或自动建表工具
CodeIgniter 的 dbforge 和迁移类(Migration)默认依赖文件路径或持久化元信息,而 :memory: 没有磁盘路径、不保存 schema 到磁盘,导致 $this->dbforge->create_table() 调用会静默失败或抛出 SQLSTATE[HY000]: General error。
- 建表必须手写
CREATE TABLE并用$db->query()执行 - 测试场景中建议在控制器或模型的构造函数里一次性建好所有表,避免重复执行
- 不要试图用
db->list_tables()检查表是否存在——它在内存库中可能返回空数组,即使表已存在
性能和生命周期要注意这些边界
内存数据库不是“更快的 SQLite 文件”,它的行为和生命周期受 PHP 请求周期严格约束:
- 每个 HTTP 请求启动一个独立的
:memory:实例,请求结束即销毁全部数据 - 同一请求内多次
$this->load->database()会复用已有连接,但不会自动重连已关闭的句柄 - 事务提交后数据仍在内存中,但无法被其他进程或后续请求访问
- 不适合做单元测试的全局 fixture——每次
setUp()都得重建表结构
最易忽略的是:你写的测试代码里如果用了 get_instance()->db 直接操作,而没走 $this->load->database() 流程,那根本连不到内存库,而是 fallback 到 default 组。


















