From a practical view there are two types of error messages when using transactions:
-"Normal" errors: in this case, the application should stop the current process and show an error message to the user.
-Deadlock errors. This shows that the deadlock detection process of PostgreSQL found a circle of dependency, and broke it by rolling back the transaction in one of the processes, which gets this error msg. In this case, the application should not stop, but repeat the transaction.
I found no discrete way to find out which case are we dealing with. This interface doesn't support error codes, so we have to search for patterns in the message text.
Here is an example for PostgreSQL database connection class. It throws a PostgresException on "normal" errors, and DependencyException in the case of a broken deadlock, when we have to repeat the transaction.
postgres.php:
<?php
class PostgresException extends Exception {
function __construct($msg) { parent::__construct($msg); }
}
class DependencyException extends PostgresException {
function __construct() { parent::__construct("deadlock"); }
}
class pg {
public static $connection;
private static function connect() {
self::$connection = @pg_connect("dbname=foodb user=foouser password=foopasswd");
if (self::$connection === FALSE) {
throw(new PostgresException("Can't connect to database server."));
}
}
public static function query($sql) {
if (!isset(self::$connection)) {
self::connect();
}
$result = @pg_query(self::$connection, $sql);
if ($result === FALSE) {
$error = pg_last_error(self::$connection);
if (stripos($error, "deadlock detected") !== false) throw(new DependencyException());
throw(new PostgresException($error.": ".$sql));
}
$out = array();
while ( ($d = pg_fetch_assoc($result)) !== FALSE) {
$out[] = $d;
}
return $out;
}
}
?>
It should be used in this way:
test.php:
<?php
include("postgres.php");
do {
$repeat = false;
try {
pg::query("begin");
...
$result = pg::query("SELECT * FROM public.kitten");
...
pg::query("commit");
}
catch (DependencyException $e) {
pg::query("rollback");
$repeat = true;
}
} while ($repeat);
?>
The normal errors should be caught at the frontend.
Tamas
pg_last_error
(PHP 4 >= 4.2.0, PHP 5)
pg_last_error — 特定の接続から直近のエラーメッセージ文字列を取得する
説明
string pg_last_error
([ resource
$connection
] )
pg_last_error() は、指定した
connection から直近のエラーメッセージを返します。
エラーメッセージは、内部的な PostgreSQL(libpq) 関数コールにより 上書きされる可能性があります。PostgreSQL モジュール関数の中で複数の エラーが発生した場合には、この関数は適切なエラーメッセージを返さない 可能性があります。
エラー処理を改善するために pg_result_error()、 pg_result_error_field()、 pg_result_status() および pg_connection_status() を使用ください。
注意:
この関数は、以前は pg_errormessage() と呼ばれていました。
パラメータ
-
connection -
PostgreSQL データベース接続リソース。
connectionが指定されていない場合はデフォルトの接続が使用されます。 デフォルトの接続は、直近の pg_connect() あるいは pg_pconnect() によって作成されたものです。
返り値
指定した connection の直近のエラーメッセージを
含む文字列を返します。エラー時には FALSE を返します。
例
例1 pg_last_error() の例
<?php
$dbconn = pg_connect("dbname=publisher") or die("接続できませんでした");
// 失敗するクエリ
$res = pg_query($dbconn, "select * from doesnotexist");
echo pg_last_error($dbconn);
?>
Tamas Bolner ¶
2 years ago
