ora-12154是php(oci8/pdo_oci)解析tns别名失败,非网络或数据库问题;需确认tns_admin/ oracle_home环境变量被php进程继承、tnsnames.ora路径权限正确、内容无bom/空格/括号错误,或直接改用easy connect格式(如//host:port/service_name)绕过解析。

ORA-12154 错误在 CodeIgniter4 连接 Oracle 时出现,说明 CI4 的 PHP 进程(通过 OCI8 或 PDO_OCI)在解析连接别名(如 @ORCL)时失败——它没找到、没读到、或读错了 tnsnames.ora。这不是数据库没开、密码错、网络不通的问题,而是客户端“压根不知道你要连哪台机器、哪个端口、哪个服务名”。排查重点全在 PHP 运行环境与 Oracle 客户端配置的匹配上。
确认 PHP 实际使用的 Oracle 客户端路径
CodeIgniter4 本身不管理 Oracle 配置,它依赖 PHP 的 OCI8 扩展所链接的 Oracle Instant Client 或完整客户端。关键是要知道 PHP 在哪找 tnsnames.ora:
- 运行
php -i | grep -i "oracle\|tns",看输出中OCI8 Support是否 enabled,并留意ORACLE_HOME或Oracle Version对应的安装路径 - 在 CI4 中临时加一行代码验证:
var_dump(getenv('TNS_ADMIN'), getenv('ORACLE_HOME'));—— PHP 进程是否继承了你设置的环境变量?很多 Web 服务器(如 Apache、Nginx + PHP-FPM)默认不继承用户 shell 的环境变量 - Linux/macOS 下,
tnsping ORCL命令用的是当前 shell 环境,但 PHP 可能跑在另一个用户/上下文里,结果不同很正常
强制指定 TNS_ADMIN 并验证文件可读
不要依赖自动查找,显式告诉 PHP 去哪读配置:
- 在 CI4 的
.env文件顶部或入口文件public/index.php开头添加:putenv('TNS_ADMIN=/path/to/your/tnsnames_dir'); - 确保该目录下存在
tnsnames.ora,且 PHP 进程有读权限(Linux 上检查ls -l /path/to/tnsnames_dir/tnsnames.ora) - 文件内容必须严格合规:别名顶格写(无空格/制表符)、括号成对、等号前后无多余空格、无 BOM 头、无中文字符。最小可用示例:
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = db.example.com)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = orclpdb1))
)
绕过 tnsnames.ora,改用 Easy Connect 字符串
最稳妥的方式是不依赖 tnsnames.ora,直接在 CI4 数据库配置中写完整地址:
- 修改
app/Config/Database.php中 Oracle 组的'DSN'或'hostname'/'port'/'database'字段 - 推荐格式(Oracle 12c+ PDB 环境):
//db.example.com:1521/orclpdb1 - 旧版 SID 格式(非多租户):
db.example.com:1521:ORCL - 这样完全跳过 TNS 解析环节,ORA-12154 自然消失
检查 OCI8 扩展与 Instant Client 版本兼容性
如果用了 Oracle Instant Client,版本错配会导致静默加载失败,进而无法解析任何 TNS 名称:
- PHP 的 OCI8 扩展需与 Instant Client 主版本一致(如 oci8 3.2 要求 client 19.x 或 21.x)
- Linux 上用
ldd $(php-config --extension-dir)/oci8.so | grep oracle确认链接的 so 文件路径是否正确 - Windows 上检查
PATH是否包含 Instant Client 目录,且顺序靠前(避免系统其他 Oracle 客户端干扰)











