カーソルを使用してテーブル内の行を処理するストアドプロシージャがあります。この手順はほとんどの場合機能しますが、完全に実行されない場合もあります。特定の行と変数を専用のデバッグテーブルに記録する、コードに埋め込まれた単純なデバッグ機能があるため、これを知っています。最も興味深いのは、PHPから実行しているときに問題が常に発生することです。mysqlクライアントを使用する場合、この問題は発生しません。
手順(ここでは少し短縮して示しています)は次のとおりです。
CREATE PROCEDURE findnextedge(IN lastid BIGINT)
findnext_context:BEGIN
DECLARE stop BOOLEAN DEFAULT FALSE;
DECLARE count INT DEFAULT 0;
DECLARE cur_fid BIGINT DEFAULT 0;
DECLARE cur_pid1 BIGINT DEFAULT 0;
DECLARE cur_pid2 BIGINT DEFAULT 0;
DECLARE cur CURSOR FOR SELECT fid, pid1, pid2 FROM edges WHERE pid1 = lastid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET stop = TRUE;
CALL debuglog(0, 'findnextedge', 'lastid', lastid, NULL, NULL, NULL, NULL);
SELECT SQL_CALC_FOUND_ROWS fid FROM edges WHERE pid1 = lastid;
SET count = FOUND_ROWS();
CALL debuglog(1, 'findnextedge', 'count', count, NULL, NULL, NULL, NULL);
IF count = 0 THEN
DELETE FROM paths WHERE pid1 = lastid AND pid2 = 0;
SELECT COUNT(*) INTO count FROM paths WHERE pid2 = 0;
CALL debuglog(2, 'findnextedge', 'count', count, NULL, NULL, NULL, NULL);
IF count = 0 THEN
SET @count = 1;
END IF;
LEAVE findnext_context;
END IF;
DELETE FROM paths WHERE pid1 = lastid AND pid2 = 0 ORDER BY pid1 LIMIT 1;
OPEN cur;
CALL debuglog(6, 'findnextedge', 'open', TRUE, NULL, NULL, NULL, NULL);
REPEAT
FETCH cur INTO cur_fid, cur_pid1, cur_pid2;
CALL debuglog(7, 'findnextedge', 'stop', stop, NULL, NULL, NULL, NULL);
IF stop = FALSE THEN
CALL debuglog(3, 'findnextedge', 'cur_fid', cur_fid, 'cur_pid1', cur_pid1, 'cur_pid2', cur_pid2);
// DO MAIN JOB
// ...
CALL debuglog(5, 'findnextedge', NULL, NULL, NULL, NULL, NULL, NULL);
END IF;
CALL debuglog(8, 'findnextedge', 'stop', stop, NULL, NULL, NULL, NULL);
UNTIL stop = TRUE
END REPEAT;
CLOSE cur;
END;
問題が発生した場合に生成される出力全体:
point context name1 value1 name2 value2 name3 value3 counter time
0 findnext lastid 0 NULL NULL NULL NULL 0 2012-11-27 18:29:56
1 findnext count 1 NULL NULL NULL NULL 1 2012-11-27 18:29:56
6 findnext open 1 NULL NULL NULL NULL 2 2012-11-27 18:29:56
7 findnext stop 0 NULL NULL NULL NULL 3 2012-11-27 18:29:56
ログによると、ポイント7では、カーソル値をフェッチした直後stop
はfalseですが、実行はポイント3にも8にも到達しません。
内部エラーが発生しているようですが、どうすればトラップできるかわかりません。不思議なことに、これはまったく同じデータで時々発生し、それ以外の場合は機能します。
PS MySQLバージョン5.0.51b、PHP5.2.6。
PSS私は関連する質問を見つけることができました-続行ハンドラーをトリップせずに、カーソルループ内でストアドプロシージャを呼び出します。私のプロシージャの名前が示すように、外部プロシージャのループ内から呼び出されるため(ちなみに、「パス」テーブルを介したループと別の続行ハンドラがあります)、これらの状況に似ている可能性があります。どういうわけか重要です。リンクされた質問から解決策を試しましたが、どちらも役に立ちませんでした。
解決策が見つかりました。答えは以下に掲載されています。