PDO连接SQLite报“could not find driver”是因为pdo_sqlite扩展未启用,需在php.ini中取消extension=pdo_sqlite注释,确保extension=pdo在前、extension=pdo_sqlite紧随其后,并重启Web服务器或PHP-FPM。

pdo_sqlite扩展没启用,连文件都会报“could not find driver”
PHP 8.0 默认不自动加载 pdo_sqlite,哪怕你装了宝塔或 phpbrew,也得手动确认扩展已启用。否则 new PDO('sqlite:/path/to/db.db') 一执行就抛 PDOException: could not find driver——这不是路径错,是驱动根本没注册。
验证方式很简单:php -m | grep pdo_sqlite。如果没输出,说明没启;有输出但 Web 环境仍失败,大概率是 CLI 和 Web 使用了不同 php.ini(php --ini 查真实路径)。
- 宝塔用户:进「网站 → PHP 设置 → 安装扩展」,勾选
pdo_sqlite和sqlite3(二者缺一不可,PDO 用前者,原生 SQLite3 类用后者) - phpbrew 用户:重装时加
+sqlite+pdo变体,如phpbrew install 8.0 +sqlite+pdo - Linux 手动编译用户:确保 configure 时含
--with-sqlite3和--enable-pdo --with-pdo-sqlite - 改完 php.ini 后必须重启 PHP-FPM(
sudo systemctl restart php8.0-fpm)或 Apache/Nginx,否则配置不生效
DSN写成相对路径,PHP运行用户没权限就静默失败
SQLite 不像 MySQL 那样走网络协议,它直接读写文件。所以 DSN 必须是绝对路径,且 PHP 进程用户(通常是 www 或 www-data)对该路径有读写权限。写成 sqlite:app.db 或 sqlite:./data/app.db,几乎必然失败——不是报错,而是连接返回 false 或空对象,后续 exec() 直接崩溃。
正确写法只有一种:sqlite:/www/wwwroot/example.com/data/app.db。注意三点:
立即学习“PHP免费学习笔记(深入)”;
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 开头必须是
sqlite:(冒号不能少),后面跟完整绝对路径 - 路径所属目录需
chown www:www /www/wwwroot/example.com/data并chmod 755(目录)和644(已有 db 文件)或664(允许 PHP 写入) - 首次连接时若文件不存在,PHP 会自动创建,但前提是父目录可写;否则报
unable to open database file
事务中遇到 SQLITE_BUSY,不能只靠 try/catch
SQLite 是文件锁,高并发写入极易触发 SQLSTATE[HY000]: General error: 5 database is locked。PDO 默认不重试,beginTransaction() 失败就直接抛异常,前端看到 500。
必须自己实现退避重试逻辑,尤其在日志、计数器等写密集场景:
- 捕获
$e->getCode() === '5'(不是字符串"5",是整数 5) - 用
usleep(100000 * pow(2, $i))做指数退避,最多试 3–5 次 - 别在事务外重试——每次重试都得重新
beginTransaction(),否则状态错乱 - 注意:SQLite 的
inTransaction()在自动回滚后可能仍返回true,不能依赖它判断当前是否在事务中
用 PDO 还是 SQLite3 类?看你要不要跨库抽象
如果你只用 SQLite,new SQLite3('/path/to.db') 更轻量、错误提示更直白;但一旦未来要切 MySQL 或 PostgreSQL,就得全量重写数据访问层。
PDO 的价值在于统一接口:sqlite: 和 mysql: DSN 切换只需改一行,预处理语法完全一致。但代价是:
- PDO SQLite 不支持
PRAGMA journal_mode = WAL这类底层优化(得用SQLite3::exec()单独调) -
PDO::lastInsertId()在 SQLite 中返回的是最后插入行的 rowid,不是自增主键值(除非主键是 INTEGER PRIMARY KEY) - 批量插入时,PDO 默认每条
INSERT单独提交,性能差;必须显式beginTransaction()+commit()包裹才有效
文件路径权限、扩展启用状态、DSN 格式、锁处理逻辑——这四点漏掉任一个,PDO 连 SQLite 就会卡在最基础环节。别跳过验证步骤,尤其别信“宝塔默认全开了”。


















