原生phppdo几个处理
闲来无事,便记录几个最近遇到的Pdo细节问题,平常都是用orm的。
长连接
在历史的Mysql驱动中,都是使用connect和pconnect来区分长短连接,到了pdo之后,改成了参数。
PDO::ATTR_PERSISTENT
$dbh = new PDO(MYSQL_DSN, MYSQL_USER, MYSQL_PASS, array( PDO::ATTR_PERSISTENT => true,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
));
如果想使用持久连接,必须在传递给 PDO 构造函数的驱动选项数组中设置 PDO::ATTR_PERSISTENT 。如果是在对象初始化之后用 PDO::setAttribute() 设置此属性,则驱动程序将不会使用持久连接。
MySQL server has gone away
某个mysql长连接很久没有新的请求发起,达到了server端的timeout,被server强行关闭。此后再通过这个connection发起查询的时候,就会报错server has gone away,这种情况特别容易出现在脚本里。(max_allowed_packet 是包太大造成的连接中断,这里不予以讨论)
解决方案:
修改my.cnf的 wait_timeout、interactive_timeout
在连接里初始化后执行sql,sql = "set interactive_timeout=秒数";
明明是长连接,但是为什么会产生是去连接呢?
错误与错误处理
PDO 提供了三种不同的错误处理模式,以满足不同风格的应用开发
- PDO::ERRMODE_SILENT
- PDO::ERRMODE_WARNING
- PDO::ERRMODE_EXCEPTION
PDO::ERRMODE_SILENT
此为默认模式。
PDO 将只简单地设置错误码,可使用 PDO::errorCode() 和 PDO::errorInfo() 方法来检查语句和数据库对象。
如果错误是由于对语句对象的调用而产生的,那么可以调用那个对象的 PDOStatement::errorCode() 或 PDOStatement::errorInfo() 方法。
如果错误是由于调用数据库对象而产生的,那么可以在数据库对象上调用上述两个方法。
PDO::ERRMODE_WARNING
除设置错误码之外,PDO 还将发出一条传统的 E_WARNING 信息,所以一般用于调试。
PDO::ERRMODE_EXCEPTION
除设置错误码之外,PDO 还将抛出一个 PDOException 异常类并设置它的属性来反射错误码和错误信息。
异常模式另一个非常有用的是,相比传统 PHP 风格的警告,可以更清晰地构建自己的错误处理,而且比起静默模式和显式地检查每种数据库调用的返回值,异常模式需要的代码/嵌套更少。
demo(异常模式):
<?php$dsn = "mysql:dbname=testdb;host=127.0.0.1";
$user = "dbuser";
$password = "dbpass";
try {
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
默认模式:
try { $pdo = Mysql::getInstance();
$pdo = $pdo->getPdo();
$sql = sprintf("insert into ".$this->getTableName()." (`job_number`, `point_data`, `sign_time`)
values("%s","%s","%s")",
$this->jobNum, $this->__toString(), date("Y-m-d H:i:s"), date("Y-m-d H:i:s", $this->verifyTimeMillis/1000));
$sth = $pdo->prepare($sql);
if ($sth) {
if ($sth->execute()) {
$this->id = $pdo->lastInsertId();
$success = true;
break;
}
$code = $sth->errorCode();
if($code == "23000") {
$success = true;
//["23000",1062,"Duplicate entry "1698-2019-11-26 13:43:57" for key "job_number_time_unique""]
if($this->id == 0) {
$this->checkExists();
}
break;
}
if($code == "HY000") {
Mysql::getInstance()->reConnection();
continue;
}
if(!empty($code)) {
Logs::writeErrorLog("数据操作失败 db error code:". $code."message:".json_encode($info));
continue;
}
if($code == "42S02") {
$this->autoCreateTable();
}
} else {
throw new Exception("insert db error with content:" . $this->__toString());
}
} catch (Exception $exception) {
$e = $exception;
}
以上是 原生phppdo几个处理 的全部内容, 来源链接: utcz.com/z/531562.html