PHP PDO连接不存在的CockroachDB数据库为何不触发错误
原因说明
- 你使用的CockroachDB v21.1版本未对齐PostgreSQL的连接校验逻辑:该版本只会在连接阶段校验网络连通性、SSL证书有效性、账号权限,不会校验你传入的
dbname是否真实存在,所以只要前几项校验通过,new PDO()就会返回成功的连接对象,不会抛出你预期的数据库不存在异常。 - 只有当你通过该连接执行实际SQL操作时,服务端才会尝试定位你指定的数据库下的对象,此时如果数据库不存在,服务端无法找到对应表的schema,就会返回
relation "recipes" does not exist这类表不存在的错误。
修复方案
- 主动追加数据库存在性校验
在new PDO()执行成功后,立刻执行校验语句,捕获异常后返回对应错误:
try { $this->link = new PDO('pgsql:host='.$this->serverName.';port=26257;dbname='.$usedb.';sslmode=require;sslrootcert='.$rootcert.';sslkey='.$userkey.';sslcert='.$usercert, $this->userName, null, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); // 新增校验逻辑 $checkStmt = $this->link->prepare("SELECT 1 FROM pg_database WHERE datname = ?"); $checkStmt->execute([$usedb]); if (!$checkStmt->fetch()) { echo 'Error Message: database ' . $usedb . ' not found'; exit(1); } } catch (PDOException $e) { echo 'Caught PDOException<br>'; echo 'Error Message: '.$e->getMessage(); echo '<br/>Error Code: '.$e->getCode(); exit(1); }
- 升级CockroachDB版本
更高版本的CockroachDB已经修改了该逻辑,连接时指定不存在的数据库会直接在连接阶段返回错误,new PDO()会直接抛出对应异常,符合你的预期。 - 调整PDO配置项
你可以在PDO初始化的配置数组中追加PDO::ATTR_EMULATE_PREPARES => false,关闭预处理模拟,部分场景下也可以触发连接阶段的数据库存在性校验。
内容的提问来源于stack exchange,提问作者Nathan Weiler
相关产品推荐
相关产品推荐

