データベースリソースを取得し、実行中はロックされているとマークし、完了したらロックされていないとマークする必要があるいくつかのPHPコードに取り組んでいます。ロックは起動時にテーブルの値を更新することで取得されます。スクリプトが何らかの理由で終了したときにロックを解除するシャットダウン関数を登録しました。
私が抱えている問題は、サーバー (Microsoft SQL データベース サーバー) への接続が実際の環境ではあまり信頼できないように見えることであり、それがスクリプトの異常終了の通常の理由のようです。明らかに、接続していないときにデータベース リソースのロックを解除することはできませんが、少なくともそれをきれいに行うために失敗を処理できるようにしたいと考えています。
以下は、メイン スクリプトの大幅に削減されたバージョンです。
try {
echo "Connecting to server...\n";
$obj_adaptor = get_remote_db ();
echo "Beginning sync...\n";
if (FALSE != ($bol_locked = $obj_adaptor -> lock_server_db ())) {
// Do work here
} else {
throw new RuntimeException ("Failed to obtain remote database lock!");
}
} catch (Exception $obj_ex) {
echo "Operation failed with an exception!\n\n";
echo "Details: \n";
echo $obj_ex -> getMessage () . PHP_EOL;
echo $obj_ex -> getTraceAsString () . PHP_EOL;
}
私のシャットダウン機能は次のようになります。
$arr_shutdown_func = function () {
global $bol_locked, $obj_adaptor;
if ($bol_locked) {
echo "Releasing lock...\n";
try {
echo $obj_adaptor -> unlock_server_db ()?
"Done\n":
"Failed to unlock database! Use force_remote_db_unlock script to force a database unlock\n";
} catch (PDOException $obj_ex) {
echo "Failed to unlock database! Use force_remote_db_unlock script to force a database unlock\n";
}
} else {
echo "No lock to release\n";
}
};
// Set up ctrl-c listener
if (function_exists ('pcntl_signal')) {
pcntl_signal (SIGINT, $arr_shutdown_func);
pcntl_signal (SIGTERM, $arr_shutdown_func);
// Register shutdown functions
register_shutdown_function ($arr_shutdown_func);
set_exception_handler ($arr_shutdown_func);
スクリプトがデータベースのロックを解放しようとして失敗し、ロックを解放できないというメッセージがエコーアウトされるため、接続が失われた場合に備えていました。
ただし、実際に得られるのは次のとおりです。
PHP Fatal error: Uncaught exception 'Zend_Db_Statement_Exception' with message 'SQLSTATE[HY000]: General error: 20047 DBPROCESS is dead or not enabled [20047] (severity 1) [(null)]' in Zend/Db/Statement/Pdo.php :238
シャットダウン関数で例外をキャッチできるかどうかについて決定的な答えを見つけようとしましたが、これまでのところあまり運がなかったので、まだ探しています。ただし、シャットダウン関数で例外を処理できる場合は、適用しているアプローチの何が問題なのかを教えていただければ幸いです。